一个有趣的现象

有时候,以下两种情况会同时发生:

  • 若直接比较两个值,其结果是相等的。
  • 若把两个值转为布尔值,它们可能得出完全相反的结果,即 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

字符串间的比较

字符串间的比较算法非常简单:

  1. 首先比较两个字符串的首位字符大小。
  2. 如果一方字符较大(或较小),则该字符串大于(或小于)另一个字符串。算法结束。
  3. 否则,两个字符串中的字符相等,继续取出各自的后一位字符进行比较。
  4. 重复上述步骤进行比较,直到某字符串率先用完所有字符。
  5. 如果两个字符串同时用完字符,那么它们被判定为相等,否则未结束(还有未比较的字符)的字符串更大。

 

总结

  • 比较操作符始终返回逻辑值。
  • 字符串间按“词典”顺序逐字符比较大小。【a>A ,  Unicode 编码顺序】
  • 当待比较的值类型不同时,它们会被转为数字(不包括严格相等检测)进行比较。
  • 在非严格相等 == 下,null 和 undefined 相等且各自不等于任何其他的值。
  • 在使用 > 或 < 进行比较时,需要注意变量可能为 null/undefined 的情况。比较好的方法是单独检查变量是否等于 null/undefined