null >=0 ? true:false

作者:Abinav Seelan 原文链接:blog.campvanilla.com/javascript-…


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

null > 0false,null == 0false,为什么null>=0true

有说 == 不会尝试转型,所以 null == 0成立。但我记得不转型的是===啊。
也有说转换为布尔值都为假,那'' == 0?
还有位群友给出了Number(null)==0的写法,让表达式结果为 true
但是大家都没有正面回答问题。

打开你的浏览器,按下f12,在 console 中输入

null > 0;
null == 0;
null >= 0;复制代码

看看结果是什么?
null >0 // false
null == 0// false
null >= 0 // true
神奇吗?一个值既不大于0,也不等于0,但它居然大于或等于0
一定是我的打开方式有问题,换个浏览器试试!
算了,还是查查 ECMAScript 标准吧。

抽象关系比较算法

先看看

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 typeResult
Undefined不转换
Null不转换
Boolean不转换
Number不转换
String不转换
Object转换为对象的默认值。对象的默认值通过调用内部的[[DefaultValue]]方法获得,忽略 hint 参数。

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

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

Input TypeResult
UndefinedNaN
Null+0
Number不转换
Booleantrue 转为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呢。

(如果你对>= 操作符的实际运算步骤感兴趣,可以看这个)

在探索这个问题的过程中,对这门语言又有了更深的认识。希望这篇文章可以帮助你。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值