js隐式类型转换学习总结
本文于986天之前发表,文中内容可能已经过时。
为什么会写这篇博客,因为自己类型转换规则实在记不住,直接先看练习题,都没问题就直接pass。
前置知识点:
- js基本数据类型比较的是值是否相等
- js引用数据类型比较的是引用的地址是否相等
==
比较会进行类型转换,===
必须类型相同值也相等
==
比较类型转换规则:
首先排除特殊的
null
,undefined
类型:1
2
3null == undefined; // true
0 == undefined; // false
0 == null; // false比较双方的类型相同,则进行值的判断:
1
[] == []; // false(类型相同但引用的地址不同)
比较双方的类型不同,进行类型转换,规则如下:
若其中一方为
object
且另一方为string
、number
或者symbol
, 将object
转为基本类型再进行判断1
2
3
4[] == ''; // true
[] == 0; // true
[null] == 0; // true
[undefined] == 0; // true若其中一方为
boolean
, 将boolean
转为number
再进行判断1
2true == 1; // true
false == 0; // true若双方类型为
string
和number
, 将string
转换成number
1
'12' == 12; // true
object
转换成基本类型规则:
object
这种复杂类型转换成基本类型时,会调用对象的valueOf
和toString
方法。
1 | {}.toString(); // '[object Object]' |
valueOf
和toString
方法调用顺序:
- 若显示定义了
[Symbol.toPrimitive]
属性,只调用该接口,若返回的不是基本数据类型,抛出错误。- 默认的调用规则:
- 非
Date
类型对象,hint
是default
时,调用顺序为:valueOf
>>>toString
,即valueOf
返回的不是基本数据类型,才会继续调用toString
,如果toString
返回的还不是基本数据类型,那么抛出错误。- 如果
hint
是string
(Date对象默人的hint是string) ,调用顺序为:toString
>>>valueOf
,即toString
返回的不是基本数据类型,才会继续调用valueOf
,如果valueOf
返回的还不是基本数据类型,那么抛出错误。- 如果
hint
是number
,调用顺序为:valueOf
>>>toString
。
1 | (new Date()).toString(); // 'Sun Jun 30 2019 16:53:46 GMT+0800 (中国标准时间)' |
关于
hint
,[Symbol.toPrimitive]
示例可访问上文引用链接
关于[Symbol.toPrimitive]
可参考:- 阮一峰·ECMAScript 6 入门
string
转换成number
规则:
Number()
和parseInt()
方法
1 | Number('12abc'); // NaN |
parseInt()
经典面试题
String()
和toString()
方法
1 | undefined.toString(); // TypeError: Cannot read property 'toString' of undefined |
radix
为2时,NumberObject会被转换为二进制值表示的字符串1
2var num = 13;
console.log(num.toString(2));
typeof
判断类型:
typeof
方法返回值:undefined
, boolean
, number
, string
, symbol
, function
, object
1 | typeof null; // 'object' |
练习题
[]
开辟了一块堆内存,地址存在栈内存,![]
返回false
1
2
3if ([]) {
... // true
}比较双方的类型相同,则进行值的判断,栈内存地址不同
1
2[] == []; // false
{} == {}; // false解题参考:- 【面试篇】寒冬求职季之你必须要懂的原生JS(上)
1
2
3[] == ![] // true
{} == !{} // false
{} == '[object Object]' // true
疑惑:文中最后一步Number([])
确实为0,但是和object
转换成基本类型规则:似乎有冲突。
- 运算符进行隐式类型转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14'12' + 1; // '121'(String)
1 + 'true'; // '1true'
1 + true; // 2
1 + undefined; // NaN
1 + null; // 1
'12' * 1; // 12(Number)
'12' - 1; // 11(Number)
'a' - 1; // NaN
2 > '10'; //false
'2' > '10'; // true
'abc' > 'b'; // false
'abc' > 'aad'; // true
[] + {}; // '[object Object]'
[] + []; // ''
- 字符串连接符
+
:只要+
号两边有一边是字符串 - 算术运算符
+
:+
号两边都是数字
特殊类型比较
null
,undefined
,NaN
的比较1
2
3undefined == null; // true
NaN == NaN; // false
NaN == null; // falseCan (a== 1 && a ==2 && a==3) ever evaluate to true?
1
2
3if (a == 1 && a == 2 && a == 3) {
// ...
}
解答:
- 利用数组的
toString
会隐含调用Array.join
方法
1 | a = [1,2,3]; |
- 重写
Object
的toString
或者valueOf
1 | const a = { |
参考文章:
赞赏是不耍流氓的鼓励