抽象的相等不相等和类型转换

问题

如果操作数类型不匹配,抽象等式和不等式运算符(==!=)将转换它们的操作数。这种类型的强制是这些运算符结果混淆的常见原因,特别是这些运算符并不总是像人们期望的那样传递。

"" ==  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 ===)?

抽象相等(==)