相等运算符(==和===)
这两个相等运算符的使用可能会引起一些困惑。
使用==时,不同类型的值也可以被看作相等。这样的结果可能会使那些资深的JavaScript开发者都感到困惑。我们用下面的表格给大家分析一下不同类型的值用相等运算符比较后的结果。
类型(x) |
类型(y) |
结果 |
|---|---|---|
null |
undefined |
true |
undefined |
null |
true |
| 数 | 字符串 | x == toNumber(y) |
| 字符串 | 数 | toNumber(x) == y |
| 布尔值 | 任何类型 | toNumber(x) == y |
| 任何类型 | 布尔值 | x == toNumber(y) |
| 字符串或数 | 对象 | x == toPrimitive(y) |
| 对象 | 字符串或数 | toPrimitive(x) == y |
如果x和y的类型相同,JavaScript会用equals方法比较这两个值或对象。没有列在这个表格中的其他情况都会返回false。
toNumber和toPrimitive方法是内部的,并根据以下表格对其进行估值。
toNumber方法对不同类型返回的结果如下。
| 值类型 | 结果 |
|---|---|
undefined |
NaN |
null |
+0 |
| 布尔值 | 如果是true,返回1;如果是false,返回+0 |
| 数 | 数对应的值 |
toPrimitive方法对不同类型返回的结果如下。
| 值类型 | 结果 |
|---|---|
| 对象 | 如果对象的valueOf方法的结果是原始值,返回原始值;如果对象的toString方法返回原始值,就返回这个值;其他情况都返回一个错误 |
用例子来验证一下表格中的结果。首先,我们知道下面的代码输出true(字符串长度大于1)。
1 | console.log('packt' ? true : false); |
那么下面这行代码的结果呢?
1 | console.log('packt' == true); |
输出是false,为什么会这样呢?
- 首先,布尔值会被
toNumber方法转成数,因此得到packt == 1。 - 其次,用
toNumber转换字符串值。因为字符串包含字母,所以会被转成NaN,表达式就变成了NaN == 1,结果就是false。
那么下面这行代码的结果呢?
1 | console.log('packt' == false); |
输出也是false,为什么呢?
首先,布尔值会被
toNumber方法转成数,因此得到packt == 0。其次,用
toNumber转换字符串值。因为字符串包含字母,所以会被转成NaN,表达式就变成了NaN == 0,结果就是false。nan和任何值包括自己都不相等
那么===运算符呢?简单多了。如果比较的两个值类型不同,比较的结果就是false。如果比较的两个值类型相同,结果会根据下表判断。
类型(x) |
值 | 结果 |
|---|---|---|
| 数 | x和y的值相同(但不是NaN) |
true |
| 字符串 | x和y是相同的字符 |
true |
| 布尔值 | x和y都是true或false |
true |
| 对象 | x和y引用同一个对象 |
true |
如果x和y类型不同,结果就是false。我们来看一些例子。
1 | console.log('packt' === true); // false |
总结:
==的时候字符串会被toNumber进行类型转换,如果字符串是纯数字则转换成相应数字,否则会被转换成NaN