前沿技术/25.精读《null >= 0?》.md
本期精读的文章是:null >= 0?
你是如何看待 null >= 0 为 true 这个结果的呢?要么选择勉强接受,要么跟着我一探究竟吧。
javascript 在判断 a > b 时,记住下面 21 步判断法:
ToPrimitive 会按照顺序优先使用存在的值:valueOf()、toString(),如果都没有,会抛出异常。 ToPrimitive(hit Number) 表示隐转数值类型
所以 null > 0 结果为 false。
现在看看 a == b 时的表现(三等号会严格判断类型,两等号反而是最复杂的情况)。
所以 null == 0 走到了第 10 步,返回了默认的 false。
javascript 是这么定义大于等于判断的:
如果 a < b 为
false,则 a >= b 为true
所以 null >= 0 为 true,因为 null < 0 是 false.
拓展一下,我们可以通过 Symbol.toPrimitive 定义某个 class 的 ToPrimitive 行为,比如:
class AnswerToLifeAndUniverseAndEverything {
[Symbol.toPrimitive](hint) {
if (hint === 'string') {
return 'Like, 42, man';
} else if (hint === 'number') {
return 42;
} else {
// when pushed, most classes (except Date)
// default to returning a number primitive
return 42;
}
}
}
按上面的道理,我们可以举一反三:
{} >= {} // true
可是这是为何呢?
null >= {} // false
仔细读过上文应该不难发现,如果 ToPrimitive(hit Number) 出现了 NaN,将直接 return undefined,也就是打印出 false,而下面是隐式转换表,{} 的结果是 NaN,因此结果是 false。
NaN 在 javascript 是个特殊存在,只有 isNaN 可以准确判断到它,而且使用它进行比较判断时,会直接 return false.
javascript 隐式转换有一套优先级规则,而且不同值的隐式转换还需要对照表记忆,还存在 ToPrimitive(hint Number) ToPrimitive(hint String) ToPrimitive(hint Boolean) 三份表,记忆起来确实有点复杂。
因此推荐比较判断时,尽量使用 ===,通过 Typescript Flow 等强类型语言约束变量类型,尽量不要做不同类型变量间的比较。
如果你想参与讨论,请点击这里,每周都有新的主题,每周五发布。