null >=0 ? true:false

做者:Abinav Seelan 原文连接:blog.campvanilla.com/javascript-…javascript


在掘金前端群里(添加掘金酱:juejinjiang 入群)问了你们一个问题:html

null > 0false,null == 0false,为何null>=0true前端

有说 == 不会尝试转型,因此 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优化

  1. 调用 ToPrimitive(X, hint Number)
  2. 调用 ToPrimitive(y, hint Number)
  3. 若是 Type(Result(1)) 是字符串且 Type(Result(2) 是字符串,跳转到步骤16。
  4. 调用ToNumber(Result(1))
  5. 调用ToNumber(Result(2))
  6. 若是Result(4)是 NaN, 返回 undefined
  7. 若是Result(5)是 NaN, 返回undefined
  8. 若是Result(4)Result(5)是一样的数字,返回false
  9. 若是Result(4)+0并且Result(5)-0,返回false
  10. 若是Result(4)-0而且Result(5)+0,返回false
  11. 若是Result(4)+∞,返回false
  12. 若是Result(5)+∞,返回true
  13. 若是Result(5)-∞,返回false
  14. 若是Result(5)-∞,返回true
  15. 若是Result(4)数学意义上的值小于Result数学意义上的值——注意这些值都是有穷的且不都为0——返回true。不然,返回false
  16. 若是Result(2)Result(1)的前缀,返回false(若是字符串 q 能够由 字符串 p 后跟另外一个字符串 r 链接组成,那么字符串 p 就是字符串 q 的前缀。注意任何一个字符串都是其自己的前缀,由于字符串 r 能够是空字符串)。
  17. 若是Result(1)Result(2)的前缀,返回true
  18. 让 k 是最小的非负整数,这样Result(1)在 k 位置的字符和 Result(2)在 k 位置的字符会不同。(由于两个字符串都不是另外一个字符串的前缀,因此必定存在这个 k)
  19. 让 m 是 Result(1)中 k 位置字符的编码值。
  20. 让 n 是 Result(2)中 k 位置字符的编码值。
    21.若是 m<n ,返回true。不然,返回false

null>0在整个算法中过一遍。
步骤一与步骤二null0上调用ToPrimitive()分别将这两个值转换为原始类型(好比NumberString)。ToPrimitive的结果以下表:编码

Input type Result
Undefined 不转换
Null 不转换
Boolean 不转换
Number 不转换
String 不转换
Object 转换为对象的默认值。对象的默认值经过调用内部的[[DefaultValue]]方法得到,忽略 hint 参数。

根据上表,null0都没有转换。spa

因此步骤三对咱们就不适用了,跳过步骤三。步骤四与步骤五须要将左右值均转换为Number类型。Number转换规则以下:

Input Type Result
Undefined NaN
Null +0
Number 不转换
Boolean true 转为1 ,false 转为 +0
... ...

(StringObject 的转换省掉了,由于暂时用不上。若是你好奇能够看这个🙃)

null转换为+00仍是0。两个值都不是NaN,因此步骤六与步骤七能够跳过。步骤八要注意下,+0等于0,因此算法返回false。因此,

null > 0;//false
 and
null < 0;//alse false复制代码

抽象相等比较算法

如今再来看看,
null == 0//false
这也很是有趣。

==操做符利用抽象相等比较算法判断true或者false

  1. 若是 Type(x)Type(y) 不一致,跳转至步骤十四。
  2. 若是Type(x)undefined, 返回 true
  3. 若是 Type(x)Null,返回 true
  4. 若是 Type(x) 不是数字,跳转到步骤十一。
  5. 若是 xNaN, 返回 false
  6. 若是 yNaN, 返回 false
  7. 若是 xy 是同一个数,返回 true
  8. 若是 x+0y-0,返回 true
  9. 若是 x-0y+0,返回 true
  10. 返回 false
  11. 若是 Type(x) 是字符串,当 xy 是彻底相同的序列时(长度一致,对应位置的字符也同样。)返回 true。不然返回 false
  12. 若是 Type(x) 是布尔值,当 xy 都为 true 或都为 false 时,语句返回 true,不然返回 false
  13. xy 指向同一个对象或指向的两个对象是联合对象(参见 13.1.2)时,返回 true ,不然返回 false
  14. 若是 xnullyundefined,返回 true
  15. 若是 xundefinedynull ,返回 true
  16. 若是 Type(x)NumberType(y) 是字符串,返回 x == [ToNumber](http://interglacial.com/javascript_spec/a-9.html#a-9.3)(y) 的结果。
  17. 若是 Type(x)StringType(y) 是数字,返回 [ToNumber](http://interglacial.com/javascript_spec/a-9.html#a-9.3)(x)==y的结果。
  18. 若是 Type(x) 是布尔值,返回 ToNumber(x) == y的结果。
  19. 若是 Type(y) 是布尔值,返回 x ==ToNumber(y)的结果。
  20. 若是 Type(x) 既不是字符串也不是数字而 Type(y) 是对象,返回 x == ToPrimitive(y) 的结果。
  21. 若是 Type(x) 是对象而 Type(y) 是字符串或数字,返回 ToPrimitive(x) == y
  22. 返回 false

判断 null0 是否相等,咱们马上从步骤一跳到步骤十四。由于 Type 不同。并且,由于Type(x) 是 null,因此步骤十四到步骤二十一也不适用。最终,步骤二十二默认返回 false。

因此,
null == 0 ; //false

大于等于操做符(>=)

如今,咱们来看最后一个表达式。
null > 0;// true
这一块标准彻底把我整蒙了。从宏观看,>=等价于

若是 null < 0false,那么 null>=0true

因此,
null >= 0; //true

老实说,这是有道理的。数学上讲,若是两个数字xyx 不小于 y,那么x 必须大于或等于y

我猜这么作的目的是为了优化比较表达式。若是能够一次比较——比较x小于y 是否成立,用这个结果推出原始表达式的结果。那干吗还要去先比较x 是否是大于y,若是不是,再比较x是否是等于y呢。

(若是你对>= 操做符的实际运算步骤感兴趣,能够看这个)

在探索这个问题的过程当中,对这门语言又有了更深的认识。但愿这篇文章能够帮助你。

相关文章
相关标签/搜索