本文主要講解JavaScript
中的三種相等運算:==
,===
和Object.is()
。經過對比和例子,加深你們的印象,並就個別例子進行詳細說明。segmentfault
ECMAScript7規範中的ToPrimitive抽象操做數組
對於x === y
,該運算符的比較步驟以下:app
x
的類型和y
的類型不同,返回false
;若是x
的類型是數字,那麼:編碼
x
是NaN
,返回false
;y
是NaN
,返回false
;x
和y
是同一個數字值,返回true
;x
是+0
,y
是-0
,返回true
;x
是-0
,y
是+0
,返回true
;false
;SameValueNonNumber(x, y)
的結果。SameValueNonNumber(x, y)
抽象操做比較兩個非數字而且同類型的x
和y
是否相等,比較步驟以下:code
x
的類型是null
或者undefined
,返回true
;若是x
是字符串類型,對象
x
和y
是徹底相同的字符編碼序列,返回true
,不然返回false
;若是x
是布爾類型,ip
x
和y
同爲true
或者false
,返回true
,不然返回false
;若是x
是symbol
類型,字符串
x
和y
是相同的符號值,返回true
,不然返回false
;x
和y
是同一個對象值,返回true
,不然返回false
。須要注意的點是NaN
,+0
,-0
:get
NaN === NaN // false +0 === -0 // true -0 === +0 // true
這三個例子分別對應x === y
比較步驟中的2.1
,2.4
和2.5
。這三個例子的輸出結果徹底就是按照規範的定義得出的結果,沒有爲何,規範就是這麼定義的。至於說爲何規範要這樣定義,可能就須要去問規範的制定者了,這個就不在本文的討論範圍以內了。string
對於Object.is(x, y)
,會使用抽象操做SameValue(x, y)
進行比較,該抽象操做的步驟以下:
x
的類型和y
的類型不同,返回false
;若是x
的類型是數字,那麼:
x
和y
都是NaN
,返回true
;x
是+0
,y
是-0
,返回false
;x
是-0
,y
是+0
,返回false
;x
和y
是同一個數字值,返回true
;false
;SameValueNonNumber(x, y)
的結果。因而可知,===
和Object.is()
的區別在於對NaN
和帶符號的0
的處理:
NaN === NaN // false +0 === -0 // true -0 === +0 // true Object.is(NaN, NaN) // true Object.is(+0, -0) // false Object.is(-0, +0) // false
對於x == y
,該運算符的比較步驟以下:
x
和y
的類型相同,返回x === y
的結果;x
是null
,y
是undefined
,返回true
;x
是undefined
,y
是null
,返回true
;x
的類型是數字,y
的類型是字符串,返回x == ToNumber(y)
的結果;x
的類型是字符串,y
的類型是數字,返回ToNumber(x) == y
的結果;x
的類型是布爾類型,返回ToNumber(x) == y
的結果;y
的類型是布爾類型,返回x == ToNumber(y)
的結果;x
的類型是字符串、數字或者Symbol
中的一種,y
的類型是對象,返回x == ToPrimitive(y)
的結果;x
的類型是對象,y
的類型是字符串、數字或者Symbol
中的一種,返回ToPrimitive(x) == y
的結果;false
。上面用到了方法ToNumber
,ToNumber(x)
的步驟以下:
x
的類型是Undefined
,返回NaN
;x
的類型是Null
,返回+0
;x
的類型是布爾類型,x
爲true
返回1
,false
返回+0
;x
的類型是數字,返回x
;x
的類型是字符串,參考字符串轉化爲數字,本文不詳細介紹這塊內容;x
的類型是Symbol
,返回NaN
;若是x
的類型是對象,
primValue
的值是ToPrimitive(x, hint Number)
;ToNumber(primValue)
的結果;上面講了==
運算符的比較步驟,下面咱們講一個例子加深下印象:
[] == ![]
首先左邊的[]
是一個空數組,類型是對象,右邊是![]
,[]
是一個真值,因此![]
的結果是false
:
[] == ![] // => [] == false
而後會走到x == y
比較步驟的第7
步,返回x == ToNumber(y)
的結果,也就是:
[] == false // => [] == ToNumber(false)
由ToNumber(x)
的第3
步可知,ToNumber(false)
返回+0
:
[] == ToNumber(false) // => [] == +0
而後走到x == y
比較步驟的第9
步,返回ToPrimitive(x) == y
的比較結果:
[] == +0 // => ToPrimitive([]) == +0
ToPrimitive([])
的結果是空字符串""
,緣由請查看文章ECMAScript7規範中的ToPrimitive抽象操做。因此,上面等價於:
"" == +0
而後走到x == y
比較步驟的第5
步,返回ToNumber(x) == y
的結果:
"" == +0 // => ToNumber("") == +0
由ToNumber
操做的第5
步可知,ToNumber("")
的結果是+0
,因此也就是:
+0 == +0 // true
首先,左邊是{}
,類型是對象,右邊是!{}
,{}
是真值,因此!{}
是false
:
{} == !{} // => {} == false
而後一樣會走到x == y
比較步驟的第7
步,返回x == ToNumber(y)
的結果,也就是:
{} == false // => {} == ToNumber(false)
由ToNumber(x)
的第3
步可知,ToNumber(false)
返回+0
:
{} == ToNumber(false) // => {} == +0
而後走到x == y
比較步驟的第9
步,返回ToPrimitive(x) == y
的比較結果:
{} == +0 // => ToPrimitive({}) == +0
ToPrimitive({})
的結果是字符串"[object Object]"
,緣由請查看文章ECMAScript7規範中的ToPrimitive抽象操做。因此,上面等價於:
"[object Object]" == +0
而後走到x == y
比較步驟的第5
步,返回ToNumber(x) == y
的結果:
"[object Object]" == +0 // => ToNumber("[object Object]") == +0
由ToNumber
操做的第5
步可知,ToNumber("[object Object]")
的結果是NaN
,因此也就是:
NaN == +0 // false
因此,[] == ![]
的結果是true
,{} == !{}
的結果是false
。可能有人第一次看到[] == ![]
的時候,以爲這個的比較結果怎麼多是true
。我以爲有時候不要感性的去認識問題,按照規定的運算步驟走一遍,結果是什麼就是什麼。
x == y
比較步驟的第4步和第5步?這個問題的詳細描述是當==
運算符兩邊分別是數字和字符串類型的時候,如何證實是如步驟4
和5
描述的那般把字符串轉化成了數字,而不是把數字轉化成了字符串?
答:思路是:是否存在這樣一個例子,使得把數字轉化爲字符串後的比較結果是false
,字符串轉化爲數字後的比較結果是true
。是的,確實存在這樣的例子:
+'3.0' // 3 => 3 == 3 => true '' + 3 // '3' => '3.0' == '3' // false '3.0' == 3 // true,證實是把字符串轉化成了數字
本文講解了JavaScript
中的三種相等運算:==
,===
和Object.is()
,但願對你們有所幫助。若是本文有什麼錯誤或者不嚴謹的地方,歡迎在評論區留言。