一个有趣的现象
有时候,以下两种情况会同时发生:
- 若直接比较两个值,其结果是相等的。
- 若把两个值转为布尔值,它们可能得出完全相反的结果,即
true
和false
。
let a = 0;
alert( Boolean(a) ); // false
let b = "0";
alert( Boolean(b) ); // true
alert(a == b); // true!
对于 JavaScript 而言这种现象蛮正常的,因为它会把待比较的值转为数字后再做比较(因此 "0"
变成了 0
)。若只是将一个变量转为 Boolean
,则会使用其他的类型转换规则。
奇怪的结果:null vs 0
通过比较 null
和 0 可得:
alert( null > 0 ); // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) true
因为相等性检测 ==
和普通比较符 > < >= <=
的代码逻辑是相互独立的。
进行值的比较会把 null
转为数字,因此它被转为了 0
。这就是为什么(3)中 null >= 0
返回 true,(1)中 null > 0
返回 false。
在相等性检测 ==
中不会进行任何的类型转换。
“拒不合作”的 undefined
undefined
不应该参与任何值的比较:
alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)
-
(1)
和(2)
中返回false
是因为undefined
在比较中被转换为了NaN
,而NaN
是一个特殊的数值型取值,它与任何值进行比较都会返回false
。 -
(3)
中返回false
是因为这是一个相等性检测,而undefined
只与null
相等,不会与其他值相等。
规避错误
除了严格相等 ===
外,其他凡是有 undefined/null
参与的比较,我们都需要额外 “关照”。
除非你非常清楚自己在做什么,否则永远不要使用 >= > < <=
去比较一个可能为null/undefined
的变量。对于取值可能是 null/undefined
的变量,请按需要分别检查它的取值情况。
严格相等操作符 ===
在进行比较时不会做任何的类型转换。
null == "\n0\n" → false
null === +"\n0\n" → false
字符串间的比较
字符串间的比较算法非常简单:
- 首先比较两个字符串的首位字符大小。
- 如果一方字符较大(或较小),则该字符串大于(或小于)另一个字符串。算法结束。
- 否则,两个字符串中的字符相等,继续取出各自的后一位字符进行比较。
- 重复上述步骤进行比较,直到某字符串率先用完所有字符。
- 如果两个字符串同时用完字符,那么它们被判定为相等,否则未结束(还有未比较的字符)的字符串更大。
总结
- 比较操作符始终返回逻辑值。
- 字符串间按“词典”顺序逐字符比较大小。【a>A , Unicode 编码顺序】
- 当待比较的值类型不同时,它们会被转为数字(不包括严格相等检测)进行比较。
- 在非严格相等
==
下,null
和undefined
相等且各自不等于任何其他的值。 - 在使用
>
或<
进行比较时,需要注意变量可能为null/undefined
的情况。比较好的方法是单独检查变量是否等于null/undefined
。