JS中相等运算符 "==" 隐式转换

937 阅读4分钟

原代码片段:

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

知识点解析

目录如下:

  1. ==相等运算符运算规则;

  2. 抽象操作ToNumber;

  3. 抽象操作ToPrimitive;

  4. 数值转换Number()函数;

  5. 逻辑非!运算规则;

  6. 布尔值转换。

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的值
Booleantruefalse
String任何非空字符串空字符串
Number任何非零数字值0和NaN
Object任何对象null
undefinedundefined

------------------来自《JavaScript高级程序设计》

总结

  • 相对于相等操作符==,全等操作符===,不会进行隐式的类型转换,所以更推荐使用全等操作符。