抽象比较运算符 和 类型转换
问题
如果计算对象的类型不匹配,抽象比较运算符(== 和 !=)将转换其运算对象。这种强制转换是大多数计算结果的困惑问题的根源,通常,这些运算符并不总是像我们期待的那样转换类型:
"" == 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” 是不同的值,所以结果是 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
全局对象的 NaN 属性
NaN(Not a Number)是一个特殊值,用于期待是数值而非数值时(1 * “two”),或者当计算值无效时(Math.sqrt(-1))。
任何比较运算或关系运算 与 NaN 比较 都返回 false,甚至NaN 与自己比较。因为 NaN是一个无意义的值。
(1 * "two") === NaN //false
NaN === 0; // false
NaN === NaN; // false
Number.NaN === NaN; // false
NaN < 0; // false
NaN > 0; // false
NaN > 0; // false
NaN >= NaN; // false
NaN >= 'two'; // false
非等运算永远返回true:
NaN !== 0; // true
NaN !== NaN; // true
检查值是否是NaN:
Number.isNaN(NaN); // true
Number.isNaN(0 / 0); // true
Number.isNaN('str' - 12); // true
Number.isNaN(24); // false
Number.isNaN('24'); // false
Number.isNaN(1 / 0); // false
Number.isNaN(Infinity); // false
Number.isNaN('str'); // false
Number.isNaN(undefined); // false
Number.isNaN({}); // false
根据协议,全局函数 isNaN() 返回 true,不仅用于 NaN,还可以是任何不能转换成数字的值或表达式:
isNaN(NaN); // true
isNaN(0 / 0); // true
isNaN('str' - 12); // true
isNaN(24); // false
isNaN('24'); // false
isNaN(Infinity); // false
isNaN('str'); // true
isNaN(undefined); // true
isNaN({}); // true
ECMAScript 6定义了一个 “相同” 算法,叫做 SameValue,可以用Object.is 调用。不像 == 和 ===,Object.is() 把NaN 对待成与 NaN 相同。但是 -0 不等于 +0:
Object.is(NaN, NaN) // true
Object.is(+0, 0) // false
NaN === NaN // false
+0 === 0 // true
但是,NaN是一个数字值,意味着它不等于字符串的 “NaN”:
typeof(NaN) === "number"; //true