1. 程式人生 > >JavaScript中的==,===和Object.js()

JavaScript中的==,===和Object.js()

概述

本文主要講解JavaScript中的三種相等運算:=====Object.js()。通過對比和例子,加深大家的印象,並就個別例子進行詳細說明。

預備知識

===運算子

對於x === y,該運算子的比較步驟如下:

  1. 如果x的型別和y的型別不一樣,返回false
  2. 如果x的型別是數字,那麼:

    1. 如果xNaN,返回false
    2. 如果yNaN,返回false
    3. 如果xy是同一個數字值,返回true
    4. 如果x+0y-0,返回true
    5. 如果x-0y+0,返回true
    6. 返回false
  3. 返回SameValueNonNumber(x, y)的結果。

SameValueNonNumber(x, y)

抽象操作比較兩個非數字並且同類型的xy是否相等,比較步驟如下:

  1. 如果x的型別是null或者undefined,返回true
  2. 如果x是字串型別,

    1. 如果xy是完全相同的字元編碼序列,返回true,否則返回false
  3. 如果x是布林型別,

    1. 如果xy同為true或者false,返回true,否則返回false
  4. 如果xsymbol型別,

    1. 如果xy是相同的符號值,返回true,否則返回false
  5. 如果xy是同一個物件值,返回true,否則返回false

需要注意的點是NaN+0-0

NaN === NaN // false
+0 === -0 // true
-0 === +0 // true

這三個例子分別對應x === y比較步驟中的2.12.42.5。這三個例子的輸出結果完全就是按照規範的定義得出的結果,沒有為什麼,規範就是這麼定義的。至於說為什麼規範要這樣定義,可能就需要去問規範的制定者了,這個就不在本文的討論範圍之內了。

Object.is()

對於Object.is(x, y),會使用抽象操作SameValue(x, y)進行比較,該抽象操作的步驟如下:

  1. 如果x的型別和y的型別不一樣,返回false
  2. 如果x的型別是數字,那麼:

    1. 如果xy都是NaN,返回true
    2. 如果x+0y-0,返回false
    3. 如果x-0y+0,返回false
    4. 如果xy是同一個數字值,返回true
    5. 返回false
  3. 返回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,該運算子的比較步驟如下:

  1. 如果xy的型別相同,返回x === y的結果;
  2. 如果xnullyundefined,返回true
  3. 如果xundefinedynull,返回true
  4. 如果x的型別是數字,y的型別是字串,返回x == ToNumber(y)的結果;
  5. 如果x的型別是字串,y的型別是數字,返回ToNumber(x) == y的結果;
  6. 如果x的型別是布林型別,返回ToNumber(x) == y的結果;
  7. 如果y的型別是布林型別,返回x == ToNumber(y)的結果;
  8. 如果x的型別是字串、數字或者Symbol中的一種,y的型別是物件,返回x == ToPrimitive(y)的結果;
  9. 如果x的型別是物件,y的型別是字串、數字或者Symbol中的一種,返回ToPrimitive(x) == y的結果;
  10. 返回false

上面用到了方法ToNumberToNumber(x)的步驟如下:

  1. 如果x的型別是Undefined,返回NaN
  2. 如果x的型別是Null,返回+0
  3. 如果x的型別是布林型別,xtrue返回1false返回+0
  4. 如果x的型別是數字,返回x
  5. 如果x的型別是字串,參考字串轉化為數字,本文不詳細介紹這塊內容;
  6. 如果x的型別是Symbol,返回NaN
  7. 如果x的型別是物件,

    1. primValue的值是ToPrimitive(x, hint Number)
    2. 返回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
"" == +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。我覺得有時候不要感性的去認識問題,按照規定的運算步驟走一遍,結果是什麼就是什麼。

總結

本文講解了JavaScript中的三種相等運算:=====Object.js(),希望對大家有所幫助。如果本文有什麼錯誤或者不嚴謹的地方,歡迎在評論區留言。

參考資料

  1. es7規範