1.写出下面程序的运行结果:
console.log([] == ![]) // true
console.log([] == []) // false
console.log([] == {}) // false
console.log(new String('a') == new String('a')) // false
console.log(isNaN(NaN)) // true
console.log(isNaN('32131dsafdas')) // true
console.log(NaN === NaN) // false
console.log(NaN === undefined) // false
console.log(undefined === undefined) // true
console.log(typeof NaN) // number
console.log({} + []) // 0
console.log([] + {}) // "[object Object]"
console.log({} + {}) // "[object Object][object Object]"
console.log([]+ []) // ""
console.log({} + 1) // 1
console.log([] + 1) // "1"
隐式类型转换参考:https://blog.csdn.net/m0_37793545/article/details/87862847
前段时间看见这样一道js的题,[] == ![] 的结果,经过在chrome控制台中打印发现结果是true,才发现自己没有完全掌握好 “==”和”===”的底层比较原理。
于是查阅相关文档,关于”==” 和 “===”的总结:
“===”叫做严格运算符,”==”叫做相等运算符。
严格运算符的运算规则如下:
1、如果类型不同,就[不相等]
2、如果两个都是数值,并且是同一个值,那么[相等];如果其中至少一个是NaN,那么[不相等]。(判断一个值是否是NaN,只能用isNaN()来判断)
3、如果两个都是字符串,每个位置的字符都一样,那么[相等];否则[不相等]。
4、如果两个值都是true,或者都是false,那么[相等]。
5、如果两个值都引用同一个对象或函数,那么[相等];否则[不相等]。
6、如果两个值都是null,或者都是undefined,那么[相等]。
相等运算符的运算规则如下:
1、如果两个值类型相同,进行 === 比较。
2、如果两个值类型不同,他们可能相等。根据下面规则进行类型转换再比较:
(1)如果一个是null、一个是undefined,那么[相等]。
(2)如果任一值是字符串,另一个值是数值,在比较相等性之前先将字符串转换为数值;即是调用Number()函数。
(3)如果任一值时布尔值,则在比较相等性之前先将其转换为数值,即是调用Number()函数。
(4)如果一个是对象,另一个是数值或字符串,把对象转换成基础类型的值再比较。对象转换成基础类型,利用它的toString或者valueOf方法。 js核心内置类,会尝试valueOf先于toString;例外的是Date,Date利用的是toString转换。
再次分析 [ ] == ![ ]这道题:
(1)看见 ![ ]这个是要对空数组转成布尔类型结果得到![ ] = false,(2)发现此时符合第三条,如果任一值是布尔类型是需要将其转换为数值,即Number(false),结果为 Number(false) = 0。(3)此时得到 [ ] == 0比较,此时符合第四条
即 [ ].toString();结果为[].toString() = ” ”;(4)此时得到 ” ” == 0,发现符合第二条即Number(“”);
结果为Number(” ”) = 0;(5)此时得到 0 == 0 两个同时为数值类型比较所以结果为true;
谈谈JS中的 {} + [] 和 [] + {}
先谈谈为什么会有这种问题,这是因为js的弱类型导致的,js的弱类型,导致js的隐式类型转换频繁。比如像标题中的{} + [],[] + {},你完全不能去预测它的类型。
先来看一条在js里的隐式的rule,js在进行加法运算的时候, 会先推测两个操作数是不是number。
如果是,则直接相加得出结果。
如果其中有一个操作数为string,则将另一个操作数隐式的转换为string,然后进行字符串拼接得出结果。
如果操作数为对象或者是数组这种复杂的数据类型,那么就将两个操作数都转换为字符串,进行拼接
如果操作数是像boolean这种的简单数据类型,那么就将操作数转换为number相加得出结果
知道了这些规则的话就简单多了
先来看第一个[] + {},这是两个复杂数据结构相加的例子,按照上面的rule,我们先将两个操作数转换为string,然后进行拼接,于是
[] -----> ''
{} -----> '[object Object]'
[] + {} = '[object Object]'
再来看第二个{} + [],这也是两个复杂数据结构相加的例子,看样子与第一个没有什么差别,按理说也应该是[object Object],但是你相加的时候你会发现, 得出的答案是 0!
这是为什么呢?
原因是有的js解释器会将开头的 {} 看作一个代码块,而不是一个js对象,于是真正参与运算的是+[],就是将[]转换为number,于是得出答案0
那么我们如何证明{}被看作一个代码块而不是一个js对象呢?很简单, 我们可以在{}里写上一些语句,比如
{console.log("hello")} + []
//hello
//0