抽象的相等不相等和型別轉換

問題

如果運算元型別不匹配,抽象等式和不等式運算子(==!=)將轉換它們的運算元。這種型別的強制是這些運算子結果混淆的常見原因,特別是這些運算子並不總是像人們期望的那樣傳遞。

"" ==  0;     // true A
 0 == "0";    // true A
"" == "0";    // false B
false == 0;   // true
false == "0"; // true

"" !=  0;     // false A
 0 != "0";    // false A
"" != "0";    // true B
false != 0;   // false
false != "0"; // false

如果你考慮 JavaScript 如何將空字串轉換為數字,結果就會有意義。

Number("");    // 0
Number("0");   // 0
Number(false); // 0

解決方案

在語句 false B 中,兩個運算元都是字串(""0),因此不會有型別轉換,因為 ""0 不是相同的值,"" == "0" 就像預期的那樣是 false

消除意外行為的一種方法是確保始終比較相同型別的運算元。例如,如果你希望數值比較的結果使用顯式轉換:

var test = (a,b) => Number(a) == Number(b); 
test("", 0);        // true;
test("0", 0);       // true
test("", "0");      // true;
test("abc", "abc"); // false as operands are not numbers 

或者,如果你想要字串比較:

var test = (a,b) => String(a) == String(b);
test("", 0);   // false;
test("0", 0);  // true
test("", "0"); // false;

旁註Number("0")new Number("0") 不是一回事! 前者執行型別轉換,後者將建立一個新物件。物件通過引用而不是值進行比較,這解釋了下面的結果。

Number("0") == Number("0");         // true;
new Number("0") == new Number("0"); // false 

最後,你可以選擇使用嚴格的相等和不等式運算子,這些運算子不會執行任何隱式型別轉換。

"" ===  0;  // false
 0 === "0"; // false
"" === "0"; // false

可在此處找到對此主題的進一步參考:

應該在 JavaScript 比較中使用哪個等於運算子(== vs ===)?

抽象相等(==)