在javascript中,null>=0 为真,null==0却为假,null的值详解
1.前言
今天看见朋友们在讨论一个问题,说 null 到底和 0 是不是相等的。
听到这里,自己赶紧去写个 Demo 试一下。
什么情况?
为什么 console.log(null <= 0); 和 console.log(null >= 0); 这两条的判断是 true 呢?
2.查阅资料
如果想明确,这个问题具体是怎么回事,那么我们需要重新来回顾一下我们的 ECMAScript Language Specification (HTML version),翻译过来就是ECMAScript语言规范(HTML版本)。
2.1 内部相等性运算算法
首先我们来看一下 ES3 关于 内部相等性运算的算法实现。
2.2 内部关系运算算法
接下来我们再来看一下 ES3 关于 内部关系运算的算法实现。
2.3 ES3 的 运算符
2.3.1 ES3 的 “>” 运算符:
2.3.2 ES3 的”>=” 运算符:
2.3.3 ES3 的 “==” 运算符 :
3. 根据资料得出的内容
着重看一下,上面特意加粗的地方,我们可以明确下面三件事。
- 关系运算符 和 相等运算符 并不是一个类别的.
- 关系运算符,在设计上,总是需要运算元尝试转为一个number . 而相等运算符在设计上,则没有这方面的考虑.
- 最重要的一点,不要把 拿 a > b,a == b 的结果 想当然的去和 a >= b 建立联系. 正确的符合最初设计思想的关系是 a > b 与 a >= b是一组 . a == b 和其他相等运算符才是一组. 比如 a === b,a != b,a !== b .
那么我们就可以反过来看这个问题了。
这里引用一下 Franky大大的话。
a >= b 运算符只是简单的去对 a < b的结果取反. 我以为这是一个设计上的失误的另一个理由是 undefined,在标准中,被单拎出来.细心的你,也一定发现了这一点. 对于undefined的设计,undefined > 0,undefined < 0,undefined == 0 的结果是符合设计上,逻辑的一致性的. 而null是被遗漏的东西.直到今天早上.我重新翻阅了ES3,5.相关章节. 才恍然大悟自己没有从根本上理解到这个问题.
虽然前面的例子,我catch到了BE当初的设计思想. 但是从全局的角度来看. 从关系运算符到相等运算符,尤其是相等运算符的设计上. 真的十分混乱不堪. BE在信中提到,他对 == 的现状也很无奈. 甚至用愚蠢这个词来形容自己当初的实现(当然他还提到,当初只是为了在10天内设计出js,并跑过qa的测试用例). 即使如此,但是他仍然表示 null == 0 这个结果是他想要的.
好吧,到了这里,我也有种无力感. 我认为纵观JavaScript,对关系运算和相等运算的设计.除了混乱,我想不出还有什么词来形容它们更恰当. 这一点从,我们生产环境代码中,大量的类型检查,和防御性代码的的存在,就可以证明这一点.
同时 Franky大大还举了另外一个例子。
if(a == undefined){
...
}
}
// 上面两组完全等价,这就是一种不明确表述.
// 我们永远不知道代码编写者的目的到底是同时匹配null 和 undefined还是只匹配其中某一个
function case3(a){
if(a === null || a === undefined){
...
}
}
// case3 才是最好的表述. 我们明确知道代码编写者的意图.
// 即使很多人可能认为这个代码很愚蠢. 但我坚定的认为这才是好代码.
最后,不得不提到,我发出null >= 0 这封信后,Andrea Giammarchi 表示了对我之前看法的支持,他同我最初的看法一样,认为 null >= 0 的结果应该为 false . 并建议在 ES7 中的严格模式中,修改这个结果. 虽然同样遭到 David Bruant 的反对. 好吧为他和我的这个错误看法,默哀一分钟…
4.后记
所以写代码,写规范,都应该明确表述. 即使表述的很罗嗦,但不会引起歧义或怀疑. 这才是一份好的标准.文档,代码. 而避免歧义,和各种混乱不堪的规则,是一门语言最应遵守的设计原则.
最后也希望大家在日常的开发中,能够少遇坑。