做者: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
呢。
(若是你對>=
操做符的實際運算步驟感興趣,能夠看這個)
在探索這個問題的過程當中,對這門語言又有了更深的認識。但願這篇文章能夠幫助你。