1. 程式人生 > 其它 >JavaScript 中應該用 == 還是 ===?

JavaScript 中應該用 == 還是 ===?

  很多時候我們會對某個語言的某個特性爭論不休,通常都只是因為我們不知道它是怎麼實現的。其實解決這個疑惑的最好的方法,就是弄清楚==和===內部的實現機制。一、嚴格相等運算子===的實現

  ===被稱為 Strict Equals Operator,假設有表示式 a===b,則它的實際運算過程如下

  計算出表示式 a 的結果,並存入 lref 變數

  將 GetValue(lref) 的結果存入 lval 變數

  計算出表示式 b 的結果,並存入 rref 變數

  將 GetValue(rref) 的結果存入 rval 變數

  執行Strict Equality Comparison演算法判斷 rval===lval 並將結果直接返回

  這裡的Strict Equality Comparison演算法很關鍵,假設要計算的是 x===y,則過程如下

  1. 如果 Type(x) 和 Type(y) 不同,返回 false

  2. 如果 Type(x) 為 Undefined,返回 true

  3. 如果 Type(x) 為 Null,返回 true

  4. 如果 Type(x) 為 Number,則進入下面的判斷邏輯

  4.1. 如果 x 為 NaN,返回 false

  4.2. 如果 y 為 NaN,返回 false

  4.3. 如果 x 的數字值和 y 相等,返回 true

  4.4. 如果 x 是 +0 且 y 是 -0,返回 true

  4.5. 如果 x 是 -0 且 y 是 +0,返回 ture

  4.6. 返回 false

  5. 如果 Type(x) 為 String,則當且僅當 x 與 y 的字元序列完全相同(長度相等,每個位置上的字元相同)時返回 true,否則返回 false

  6. 如果 Type(x) 為 Boolean,則若 x 與 y 同為 true 或同為 false 時返回 true,否則返回 false

  7. 如果 x 和 y 引用的是同一個物件,返回 true,否則返回 false

  二、相等運算子==的實現

  好了,當你明白了===的實現之後,我們再來看看==的實現,比較一下他們有何不同?

  ==被稱為 Equals Operator (注意看沒有 Strict 了),假設有表示式 a==b,則它的實際運算過程如下

  計算出表示式 a 的結果,並存入 lref 變數

  將 GetValue(lref) 的結果存入 lval 變數

  計算出表示式 b 的結果,並存入 rref 變數

  將 GetValue(rref) 的結果存入 rval 變數

  執行Abstract Equality Comparison演算法判斷 rval==lval 並將結果直接返回

  注意,其中的前 4 個步驟是和===完全相同的。唯獨 5 不同。對於===來說,呼叫的是Strict Equality Comparison演算法,但是==則呼叫的是Abstract Equality Comparison演算法。雖然僅一詞之差,但是卻有質的不同,我們下面就來看看到底它是怎麼實現的

  假設要計算的是 x==y,Abstract Equality Comparison計算的過程如下(很冗長,但是每個步驟都很簡單)

  1. 如果 Type(x) 和 Type(y) 相同,則

  1.1. 如果 Type(x) 為 Undefined,返回 true

  1.2. 如果 Type(x) 為 Null,返回 true

  1.3. 如果 Type(x) 為 Number,則

  1.3.1. 如果 x 是 NaN,返回 false

  1.3.2. 如果 y 是 NaN,返回 false

  1.3.3. 如果 x 的數值與 y 相同,返回 true

  1.3.4. 如果 x 是 +0 且 y 是 -0,返回 true

  1.3.5. 如果 x 是 -0 且 y 是 +0,返回 true

  1.3.6. 返回 false

  1.4. 如果 Type(x) 為 String,則當且僅當 x 與 y 的字元序列完全相同(長度相等,每個位置上的字元相同)時返回 true,否則返回 false

  1.5. 如果 Type(x) 為 Boolean,則若 x 與 y 同為 true 或同為 false 時返回 true,否則返回 false

  1.6. 如果 x 和 y 引用的是同一個物件,返回 true,否則返回 false

  2. 如果 x 是 null 且 y 是 undefined,返回 true

  3. 如果 x 是 undefined 且 y 是 null,返回 ture

  4. 如果 Type(x) 為 Number 且 Type(y) 為 String,以 x==ToNumber(y) 的比較結果作為返回

  5. 如果 Type(x) 為 String 且 Type(y) 為 Number,以 ToNumber(x)==y 的比較結果作為返回值

  6. 如果 Type(x) 為 Boolean,以 ToNumber(x)==y 的比較結果作為返回值

  7. 如果 Type(y) 為 Boolean,以 x==ToNumber(y) 的比較結果作為返回值

  8. 如果 Type(x) 為 String 或 Number 且 Type(y) 為 Object,以 x==ToPrimitive(y) 的比較結果作為返回值

  9. 如果 Type(x) 為 Object 且 Type(y) 為 String 或 Number,以 ToPrimitive(x)==y 的比較結果作為返回值

  10. 返回 false

  三、總結

  從上面的演算法流程可以看出,a===b 是最簡單的。如果 a 和 b 的型別不同,那麼一定會返回 false。而 a==b 則要靈活得多。JavaScript 會嘗試調整 a 和 b 的型別,例如若 a 為字串 b 為數字,則將字串先轉化為數字再與 b 比較,等等。這在很多時候簡化了程式設計師的程式碼量。

  一些程式設計師害怕==而提倡使用===的根本原因是,他們不知道在==的內部具體發生了什麼。而這就導致誤用和出錯。

  很多人認為,當我們不瞭解一個 feature 的時候,我們就不用它就行了。這也許是一種習慣性邏輯。但尷尬的是你不用這個 feature 沒問題,別人卻可能還是會用。為了能讀懂別人的程式碼,我們又必須實際上搞清楚這內在的邏輯。所以最終還是得付出這方面的學習成本。