你真的理解==和===嗎

fondtiger發表於2021-09-09
開門見題

說出以下幾個表示式的結果

var obj1 = { name: '張三'}
var obj2 = obj1
var obj3 = { name: '張三'}

null == undefined
123 == '123'
false == 0
NaN == false
obj1 == obj2
obj1 == obj3
補充知識

要想回答上述問題,必須理解js在執行==時候的一些資料轉換規則和成文的規定。ECMA-262對==的約定如下:
圖片描述

x==y

  1. 如果x和y的型別相同,
    1. 如果x是undefined,return true
    2. 如果x是null,return true
    3. 如果x是Number
      1. x是NaN,return false
      2. y是NaN,return false
      3. x,y數值相同,return true
      4. x是+0,y是-0,return true
      5. x是-0,y是+0,return true
    4. 如果x是String,y必須和x長度內容都相同才return true,否則return false
    5. 如果x是Boolean,x,y相同return true,否則return false
    6. 如果x,y引用同一個物件,return true,否則return false
  2. x是null,y是undefined,return true
  3. x是undefined,y是null,return true
  4. x是Number,y是String,return x == ToNumber(y)
  5. x是String,y是Number,return ToNumber(x) == y
  6. x是Boolean,return ToNumber(x) == y
  7. y是Boolean,return x == ToNumber(y)
  8. x是String或Number,y是Object,return x == ToPrimitive(y)
  9. x是Object,y是String或Number,return ToPrimitive(x) == y
  10. return false

你可能注意到了這樣兩個函式

ToNumber()

引數型別 結果
Undefined NaN
Null +0
Boolean true為1,false為+0
Number 引數本身
String 簡單理解,能轉換成數字的就會轉換成數字,比如數字字串,十六進位制的數字等,轉換失敗則返回NaN(詳見ECMA-262-9.3.1,內容較多,不展開敘述)
Object 兩步轉換操作:1. ToPrimitive(input argument, hint Number) 2. ToNumber()

ToPrimitive()

引數型別 結果
Undefined 輸入值
Null 輸入值
Boolean 輸入值
Number 輸入值
String 輸入值
Object 呼叫DefaultValue方法

好吧,又多了一個DefaultValue方法

ToPrimitive()

細心的你發現上面ToNumber對於Object的轉換裡有這麼一句ToPrimitive(input argument, hint Number),就是說呼叫ToPrimitive的時候,除了傳入要轉化的值,還傳了一個hint引數,這個引數可以為Number,也可以為String。那麼什麼時候傳入這兩個引數,同時又有啥區別?

  • 如果引數是hint Number:

    1. 先執行valueOf,如果返回值是原始值,則返回原始值
    2. 否則執行toString,如果返回值是原始值,則返回原始值
    3. 報錯
  • 如果引數是hint String:
    1. 先執行toString,如果返回值是原始值,則返回原始值
    2. 否則執行valueOf,如果返回值是原始值,則返回原始值
    3. 報錯

如果input argument是內建的Date型別,則引數是hint String,否則預設hint Number

回到題目

說了這麼多,我們回到上面的題目,一一解答:

  1. null == undefined。根據上面第二條,寫的明明白白,結果是true。
  2. 123 == '123'。根據上面第四條return 123 == ToNumber('123'),而ToNumber('123')的結果為123,所以return 123 == 123,根據1-3-3,返回true。
  3. false == 0。根據上面第六條,return ToNumber(false) == 0,而ToNumber(false)的值為+0,所以+0 == 0,根據1-3-3,返回true。
  4. NaN == false。看到很多別的同學說這裡是做了各種型別轉換,其實我認為這裡是由於沒有匹配到任何規則,所以根據第十條返回false,也就是說並沒有做什麼型別轉換。
  5. obj1 == obj2。根據1-6,由於obj1和obj2指向同一個引用,所以返回true。
  6. obj1 == obj3。根據1-6,由於obj1和obj2指向不同引用,所以返回false。
關於===

把上面題目中的==換成===,試問結果會發生怎樣的變化?這裡我就不說了,推理方式同上,根據如下規則,答案請各位看官自行補充。
圖片描述

x===y

  1. 如果x,y型別不同,return false
  2. 如果x是undefined,return true
  3. 如果x是null,return true
  4. 如果x是Number
    • 如果x是NaN,return false
    • 如果y是NaN,return false
    • x,y數值相同,return true
    • x是+0,y是-0,return true
    • x是-0,y是+0,return true
    • return false
  5. 如果x是String,y必須和x長度內容都相同才return true,否則return false
  6. 如果x,y引用同一個物件,return true,否則return false

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2508/viewspace-2805307/,如需轉載,請註明出處,否則將追究法律責任。

相關文章