原代码片段:
var a = []
console.log(a == 0)//true
console.log(!a == 0)//true
a == 0
相当于执行了
Number(a.toString()) == 0;
Number("") == 0;
0 == 0;
!a == 0
相当于执行了
Number(!a) == 0;
Number(false) == 0;
0 == 0知识点解析
目录如下:
==相等运算符运算规则;
抽象操作ToNumber;
抽象操作ToPrimitive;
数值转换Number()函数;
逻辑非!运算规则;
布尔值转换。
1. ==相等运算符运算规则
查阅MDN得:
相等操作符对于不同类型的值,进行的比较如下图所示:

在上面的表格中,ToNumber(A) 尝试在比较前将参数 A 转换为数字,这与 +A(单目运算符+)的效果相同。ToPrimitive(A)通过尝试依次调用 A 的A.toString() 和 A.valueOf() 方法,将参数 A 转换为原始值(Primitive)。
由上面的表格也可看出,与Number类型进行相等比较时,都会转成Number类型进行比较。
参考链接:developer.mozilla.org/zh-CN/docs/…
2.抽象操作ToNumber
ES5 规范在 9.3 节定义了 抽象操作 ToNumber。
其中 true 转换为 1,false 转换为 0。
undefined 转换为 NaN,null 转换为 0。
ToNumber 对字符串的转换遵从通用规则(Number(..)函数)。处理失败时返回 NaN(处理数字常量失败时会产生语法错误)。
Number(..) 遵循 ToNumber 规则,将值转换为数字基本类型。
对象(包括数组)会首先转换成相应的基本类型值,依赖于ToPrimitive操作,如果返回的是非数字类型的基本类型值,则再遵循以上规则将其强制转换为数字。
-------------------来自《你不知道的JavaScript(中卷)》
可见,抽象操作ToNumber其实与Number()函数的行为大致相同。
3.抽象操作ToPrimitive
抽象操作 ToPrimitive(参见 ES5 规范 9.1 节)会首先 (通过内部操作 DefaultValue,参见 ES5 规范 8.12.8 节)检查该值是否有 valueOf() 方法。
如果有并且返回基本类型值,就使用该值进行强制类型转换。
如果没有就使用 toString() 的返回值(如果存在)来进行强制类型转换。
如果 valueOf() 和 toString() 均不返回基本类型值,会产生 TypeError 错误。
-------------------来自《你不知道的JavaScript(中卷)》
4. 数值转换Number()函数
Number函数的转换规则如下:
如果是Boolean值,true和false将分别转换为1和0;
如果是数字值,只是简单的传入和返回;
如果是null值,返回0;
如果是undefined,返回NaN;
如果是字符串,遵循下列规则:
如果字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值(前缀0会忽略);
如果字符串中包含有效的浮点格式,则将其转换为相对应的浮点数值;
如果字符串中包含有效的十六进制格式,则将其转为相同大小的十进制整数值;
如果字符串是空的,则将其转换为0;
如果字符串中包含上述格式之外的字符,则将其转换为NaN。
若果是对象,则调用对象的valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是NaN,则调用对象的toString()方法,然后再次一早前面的转换规则转换返回的字符串值。
---------------------来自《JavaScript高级程序设计》
5. 逻辑非!运算规则
| 运算符 | 示例 | 说明 |
|---|---|---|
逻辑与 (&&) | *expr1* &&*expr2* | 如果*expr1* 能转换成false则返回expr1,否则返回expr2。因此,与布尔值一起使用时,如果两个操作数都为true时&&返回true,否则返回false。 |
逻辑或 (||) | *expr1* ||*expr2* | 如果expr1能转换成true则返回expr1,否则返回expr2。因此,与布尔值一起使用时,如果任意一个操作数为true时 |
逻辑非(!) | !*expr* | 如果expr能转换为true,返回false;如果expr能转换为false,则返回true。 |
------------来自MDN
参考链接:developer.mozilla.org/zh-CN/docs/…
6. 布尔值转换
| 数据类型 | 转换为true的值 | 转换为false的值 |
|---|---|---|
| Boolean | true | false |
| String | 任何非空字符串 | 空字符串 |
| Number | 任何非零数字值 | 0和NaN |
| Object | 任何对象 | null |
| undefined | undefined |
------------------来自《JavaScript高级程序设计》
总结
相对于相等操作符==,全等操作符===,不会进行隐式的类型转换,所以更推荐使用全等操作符。