我们先从一组 用例说起. 看代码:
null > 0 // false
null == 0 // false
null >= 0 //true
我们今天讨论的主要内容,并不是这个结果可能看起来多么奇怪. 而是为什么会这样. 之所以特别记一篇随笔在这里,主要是因为,我在得到了 Brendan Eich 的一些确认后.发现答案和我当初的猜测不一样. 所以我有反省,自己对ES的一些理解上,是不是有些偏主观.
开始前,我们先拿ES3,ES5的相关定义说起:
注1 : ES3,ES5对关系运算符 ">" , "<", ">=", "<=" 以及相等运算符的实现,在关键部分几乎相同,所以不再列出ES5的内容.
注2 : 下面这些内容,你只需要简单注意下,我标红的部分,其他部分其实无关紧要. 我会对这些内容,在后面的部分有个大概的解释.
注3 : <= 以及 < 与之类似,不在赘述..
说明
1. 关系运算符 和 相等运算符 并不是一个类别的.
2. 关系运算符,在设计上,总是需要运算元尝试转为一个number . 而相等运算符在设计上,则没有这方面的考虑.
3. 最重要的一点, 不要把 拿 a > b , a == b 的结果 想当然的去和 a >= b 建立联系. 正确的符合最初设计思想的关系是 a > b 与 a >= b是一组 . a == b 和其他相等运算符才是一组. 比如 a === b , a != b, a !== b .
所以,我们反过来看待这个问题.
null > 0 // null 尝试转型为number , 则为0 . 所以结果为 false,
null >= 0 // null 尝试转为number ,则为0 , 结果为 true.
null == 0 // null在设计上,在此处不尝试转型. 所以 结果为false.
我个人在之前的阅读中,并没有意识到这些问题.而导致,我愚蠢的认为, >= 的结果是设计上的失误. 原因是,我简单的认为 :
Perform the comparison Result(2) < Result(4). (see 11.8.5).
If Result(5) is true or undefined, return false. Otherwise, return true.
a >= b 运算符只是简单的去对 a < b的结果取反. 我以为这是一个设计上的失误的另一个理由是 undefined,在标准中,被单拎出来.细心的你,也一定发现了这一点. 对于undefined的设计, undefined > 0 , undefined < 0, undefined == 0 的结果是符合设计上,逻辑的一致性的. 而null是被遗漏的东西.
怀着这样的想法,我给 es-discuss 写了信,用不温和的口吻.质疑这个问题. 惊喜的是, Brendan Eich 居然关注了这个问题.并立刻做出了回复. 悲剧的是,我在反复阅读该回信内容时,仍然没有从根本上理解到这个问题.直到今天早上.我重新翻阅了ES3,5.相关章节. 才恍然大悟.
到此,我的反省结束. 同时也感谢 BE 的认真,及时的回复. 作为一个CTO,任然如此关心并积极参与技术社区的发展,实在让人钦佩.
接着是吐槽的时候了:
虽然前面的例子,我catch到了BE当初的设计思想. 但是从全局的角度来看. 从关系运算符到相等运算符,尤其是相等运算符的设计上. 真的十分混乱不堪. BE在信中提到,他对 == 的现状也很无奈. 甚至用愚蠢这个词来形容自己当初的实现(当然他还提到,当初只是为了在10天内设计出js,并跑过qa的测试用例). 即使如此, 但是他仍然表示 null == 0 这个结果是他想要的.
好吧,到了这里,我也有种无力感. 我认为纵观javascript,对关系运算和相等运算的设计.除了混乱,我想不出还有什么词来形容它们更恰当. 这一点从,我们生产环境代码中,大量的类型检查,和防御性代码的的存在,就可以证明这一点.
另外一个要吐槽的地方是ES规范本身. 比如前面让我深深误解的地方 ,即 a >= b 即 对 a < b 的结果取反. 这一点上,就属于不明确表述. 我们想想一个典型的js的例子
function case1(a){
if(a == null){
....
}
}
function case2(a){
if(a == undefined){
...
}
}
// 上面两组完全等价, 这就是一种不明确表述.
// 我们永远不知道代码编写者的目的到底是同时匹配null 和 undefined还是只匹配其中某一个
function case3(a){
if(a === null || a === undefined){
...
}
}
// case3 才是最好的表述. 我们明确知道代码编写者的意图.
// 即使很多人可能认为这个代码很愚蠢. 但我坚定的认为这才是好代码.
所以写代码,写规范,都应该明确表述. 即使表述的很罗嗦,但不会引起歧义或怀疑. 这才是一份好的标准.文档,代码. 而避免歧义,和各种混乱不堪的规则,是一门语言最应遵守的设计原则.
最后, 不得不提到,我发出null >= 0 这封信后, Andrea Giammarchi 表示了对我之前看法的支持,他同我最初的看法一样,认为 null >= 0 的结果应该为 false . 并建议在 ES7 中的严格模式中,修改这个结果. 虽然同样遭到 David Bruant 的反对. 好吧为他和我的这个错误看法,默哀一分钟...
原文:https://www.cnblogs.com/_franky/archive/2012/09/26/2703723.html
在这个快速教程中,我们将看一下Null对象模式,这是设计模式的一个特例,一个经常被我们遗忘的特例。我们将描述它的目的以及我们何时应该考虑使用它。像往常一样,我们还将提供一个简单的代码示例。
js中一共有5种简单数据类型:Undefined, Null, boolean, Number, String. 还有一种复杂的数据类型:Object,本篇主要介绍Undefined和Null
null和undefined属于js中两种不同的基本数据类型,都可以表示“没有”,含义非常相似。将一个变量赋值为undefined或null,老实说,语法效果几乎没区别。并且在if语句的判断条件中,它们都会自动转为false
尽管从第一次遇到空值引起的bug开始,我就一直要求自己注意空值,但还是经常犯这样的错误,JS中的空值真的需要多加注意。这里说的空值包括undefined和null
许多 JavaScript 开发人员正在为怎么处理可选值头痛。有什么好办法来最大程度地减少由值(可能为 null、undefined或在运行时未初始化)引起的错误?在某些情况下,一些语言具有内置功能。在某些静态类型的语言中
在JavaScript中值undefined和null都表示”无”,那么它们之间有什么区别?undefined:在 JavaScript 中, undefined 是一个没有设置值的变量。typeof 一个没有值的变量会返回 undefined。null是一个只有一个值的特殊类型。表示一个空对象引用。
大多数计算机语言,有且仅有一个表示“无”的值,比如:C 语言的 NULL,Java 语言的 null,Python 语言的 None,Ruby 语言的 nil。但是在 JavaScript 中却同时存在 undefined 和 null
JavaScript 有两种类型:原始类型(strings, booleans, numbers, symbols)和对象,对象是一个复杂的数据结构。最简单的 JavaScript 对象是普通对象 —— 键和相关值的集合
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!