做者:Abinav Seelan 原文连接:blog.campvanilla.com/javascript-…javascript
在掘金前端群里(添加掘金酱:juejinjiang 入群)问了你们一个问题:html
null > 0
为false
,null == 0
为false
,为何null>=0
为true
?前端
有说 ==
不会尝试转型,因此 null == 0
成立。但我记得不转型的是===
啊。
也有说转换为布尔值都为假,那'' == 0
?
还有位群友给出了Number(null)==0
的写法,让表达式结果为 true
。
可是你们都没有正面回答问题。java
打开你的浏览器,按下f12,在 console 中输入算法
null > 0;
null == 0;
null >= 0;复制代码
看看结果是什么?null >0 // false
null == 0// false
null >= 0 // true
神奇吗?一个值既不大于0
,也不等于0
,但它竟然大于或等于0
。
必定是个人打开方式有问题,换个浏览器试试!
算了,仍是查查 ECMAScript 标准吧。浏览器
先看看bash
null > 0// false复制代码
根据标准,>
<
操做符利用抽象关系比较算法判断表达式为true
或者false
。优化
- 调用
ToPrimitive(X, hint Number)
。- 调用
ToPrimitive(y, hint Number)
。- 若是
Type(Result(1))
是字符串且Type(Result(2)
是字符串,跳转到步骤16。- 调用
ToNumber(Result(1))
。- 调用
ToNumber(Result(2))
。- 若是
Result(4)
是 NaN, 返回undefined
。- 若是
Result(5)
是 NaN, 返回undefined
。- 若是
Result(4)
和Result(5)
是一样的数字,返回false
。- 若是
Result(4)
是+0
并且Result(5)
是-0
,返回false
。- 若是
Result(4)
是-0
而且Result(5)
是+0
,返回false
。- 若是
Result(4)
是+∞
,返回false
。- 若是
Result(5)
是+∞
,返回true
。- 若是
Result(5)
是-∞
,返回false
。- 若是
Result(5)
是-∞
,返回true
。- 若是
Result(4)
数学意义上的值小于Result
数学意义上的值——注意这些值都是有穷的且不都为0——返回true
。不然,返回false
。- 若是
Result(2)
是Result(1)
的前缀,返回false
(若是字符串 q 能够由 字符串 p 后跟另外一个字符串 r 链接组成,那么字符串 p 就是字符串 q 的前缀。注意任何一个字符串都是其自己的前缀,由于字符串 r 能够是空字符串)。- 若是
Result(1)
是Result(2)
的前缀,返回true
。- 让 k 是最小的非负整数,这样
Result(1)
在 k 位置的字符和Result(2)
在 k 位置的字符会不同。(由于两个字符串都不是另外一个字符串的前缀,因此必定存在这个 k)- 让 m 是
Result(1)
中 k 位置字符的编码值。- 让 n 是
Result(2)
中 k 位置字符的编码值。
21.若是m<n
,返回true
。不然,返回false
。
将null>0
在整个算法中过一遍。
步骤一与步骤二 在null
和0
上调用ToPrimitive()
分别将这两个值转换为原始类型(好比Number
和String
)。ToPrimitive
的结果以下表:编码
Input type | Result |
---|---|
Undefined | 不转换 |
Null | 不转换 |
Boolean | 不转换 |
Number | 不转换 |
String | 不转换 |
Object | 转换为对象的默认值。对象的默认值经过调用内部的[[DefaultValue]]方法得到,忽略 hint 参数。 |
根据上表,null
和0
都没有转换。spa
因此步骤三对咱们就不适用了,跳过步骤三。步骤四与步骤五须要将左右值均转换为Number
类型。Number
转换规则以下:
Input Type | Result |
---|---|
Undefined | NaN |
Null | +0 |
Number | 不转换 |
Boolean | true 转为1 ,false 转为 +0 |
... | ... |
(String
及 Object
的转换省掉了,由于暂时用不上。若是你好奇能够看这个🙃)
null
转换为+0
而0
仍是0
。两个值都不是NaN
,因此步骤六与步骤七能够跳过。步骤八要注意下,+0
等于0
,因此算法返回false
。因此,
null > 0;//false
and
null < 0;//alse false复制代码
如今再来看看,null == 0//false
这也很是有趣。
==
操做符利用抽象相等比较算法判断true
或者false
。
- 若是
Type(x)
与Type(y)
不一致,跳转至步骤十四。- 若是
Type(x)
是undefined
, 返回true
。- 若是
Type(x)
是Null
,返回true
。- 若是
Type(x)
不是数字,跳转到步骤十一。- 若是
x
是NaN
, 返回false
。- 若是
y
是NaN
, 返回false
。- 若是
x
和y
是同一个数,返回true
。- 若是
x
是+0
且y
是-0
,返回true
。- 若是
x
是-0
且y
是+0
,返回true
。- 返回
false
。- 若是
Type(x)
是字符串,当x
与y
是彻底相同的序列时(长度一致,对应位置的字符也同样。)返回true
。不然返回false
。- 若是
Type(x)
是布尔值,当x
与y
都为true
或都为false
时,语句返回true
,不然返回false
。- 当
x
与y
指向同一个对象或指向的两个对象是联合对象(参见 13.1.2)时,返回true
,不然返回false
。- 若是
x
是null
且y
是undefined
,返回true
。- 若是
x
是undefined
且y
是null
,返回true
。- 若是
Type(x)
是Number
且Type(y)
是字符串,返回x == [ToNumber](http://interglacial.com/javascript_spec/a-9.html#a-9.3)(y)
的结果。- 若是
Type(x)
是String
且Type(y)
是数字,返回[ToNumber](http://interglacial.com/javascript_spec/a-9.html#a-9.3)(x)==y
的结果。- 若是
Type(x)
是布尔值,返回ToNumber(x) == y
的结果。- 若是
Type(y)
是布尔值,返回x ==ToNumber(y)
的结果。- 若是
Type(x)
既不是字符串也不是数字而Type(y)
是对象,返回x == ToPrimitive(y)
的结果。- 若是
Type(x)
是对象而Type(y)
是字符串或数字,返回ToPrimitive(x) == y
。- 返回
false
。
判断 null
与 0
是否相等,咱们马上从步骤一跳到步骤十四。由于 Type 不同。并且,由于Type(x) 是 null,因此步骤十四到步骤二十一也不适用。最终,步骤二十二默认返回 false。
因此,null == 0 ; //false
如今,咱们来看最后一个表达式。null > 0;// true
这一块标准彻底把我整蒙了。从宏观看,>=
等价于
若是
null < 0
是false
,那么null>=0
是true
。
因此,null >= 0; //true
老实说,这是有道理的。数学上讲,若是两个数字x
和y
,x
不小于 y
,那么x
必须大于或等于y
。
我猜这么作的目的是为了优化比较表达式。若是能够一次比较——比较x
小于y
是否成立,用这个结果推出原始表达式的结果。那干吗还要去先比较x
是否是大于y
,若是不是,再比较x
是否是等于y
呢。
(若是你对>=
操做符的实际运算步骤感兴趣,能够看这个)
在探索这个问题的过程当中,对这门语言又有了更深的认识。但愿这篇文章能够帮助你。