===
不进行数据类型转换,值和类型都相等才为true。
==
不同的数据类型之间比较时,会进行数据类型转换(通常称为强制转型),然后比较它们的相等性。
在转换不同的数据类型时,相等操作符遵循下列基本规则:
- 如果有一个操作数是布尔值,则在比较相等性之前,将其转换为数值;
- 如果一个操作数是字符串,另一个操作数是数值,在比较之前先将字符串转换为数值;
- 如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf() 方法,用得到的基本类型值按照前面的规则进行比较;
以上三点可归纳为一点:
如果相等操作符两边的操作数,不包含null或者undefined,且两个操作数不全是对象,在执行相等比较之前,会先调用Number()将两个操作数强制转为Number类型,然后进行比较:
'55' == 55; //truefalse == 0; //true"wise" == 3; //false ( Number("wise") -> NaN )[] == 0; //true ( Number([]) -> 0 )复制代码
- 如果有一个操作数是 NaN,无论另一个操作数是什么,相等操作符都返回 false;
NaN == NaN; //false复制代码
- 如果两个操作数都是对象,则比较它们是不是同一个对象。如果指向同一个对象,则相等操作符返回 true;
[] == []; //false{} == {}; //false// 实际上声明了两个变量指向不同的对象进行比较var a = [],b = ab == a // true(a和b指向同一个对象)复制代码
- 在比较相等性之前,不能将 null 和 undefined 转成其他值。
- null 和 undefined 是相等的。
null == undefined; // true复制代码
关于[] == ![] 和 {} == !{}
根据javascript的运算优先级,逻辑非 (!) 的优先级高于相等操作符 ( == ),因此先计算![]得到false,实际上是比较:
[] == false复制代码
再根据上述规则1和规则3,将两个操作数转为数字类型:
Number([]) == Number(false) -> 0 == 0 -> true复制代码
同样,{} == !{}也遵循同样的规则:
{} == !{} -> {} == false -> Number({}) == Number(false) -> NaN == 0 -> false复制代码
不同类型的数据进行==比较时的转换规则总结:
类型 | 类型 | 比较说明 |
---|---|---|
对象 | 对象 | 比较是不是同一个内存地址 |
对象 | 字符串 | 对象先转为字符串,再和字符串进行比较 |
对象 | 布尔类型 | 两边都要先转为数值(false 是 0,true 是 1)对象类型先隐式调用toString()方法,然后再Number() |
对象 | 数字 | 对象要转为数字,再进行比较(对象先隐式调用toString()方法转为字符串,然后再把字符串,转为数字使用Number()方法 |
数字 | 布尔 | 布尔转成数字(false 是 0,true 是 1),再和数字进行比较 |
数字 | 字符串 | 字符串转成数字使用Number()方法,再和数字进行比较 |
布尔 | 数字/字符串 | 都转成数字再进行比较 |
null | undefined | tru |
null/undefined | 其他类型 | 结果都是false |
NaN | NaN | false |