1. JavaScript的重载运算符“+”
这个运算符既重载的数字的相加,又重载了字符串连接操作,具体是数字相加还是字符串连接,这取决于其参数的类型。
1 + 2 + "3"; // "33"
(1 + 2) + "3"; // "33"
1 + "2" + 3; // "123"
(1 + "2") + 3; // "123"
2. 结果为NaN的错误
强制转换也会有隐藏的错误,结果为null的变量在算数运算中不会导致失败,而是被隐式的转换为0。
一个未定义的变量将被转换为特殊的浮点数值NaN。
这些强制转换不会抛出异常。
测试一个值是否等于NaN的方法根本行不通。
var x = NaN;
x === NaN; //false
isNaN(NaN); //true
isNaN("foo"); //true
isNaN(undefined); //true
isNaN({}); //true
isNaN({valueOf: "foo"}); //true
解决方法:通过检查一个值是否等于其自身的方式来测试该值是否是NaN。
function fnIsReallyNaN (x) {
return x !== x;
}
隐式的强制转换最好的调试方式是检查非预期值的中间结果,回到出错前的”最后一点”,在那里检查每个操作的参数,查看错误类型的参数。
3. 对象也可以转换
对象可以通过调用其自身的toString()方法转换为字符串,也可以通过其valueOf()的方法转换为数字。
当一个对象同时包含toString() 和 valueOf()方法时,JavaScript会盲目地选择valueOf()方法来解决这种含糊的情况。
var obj = {
toString: function () {
return "[object MyObject]";
},
valueOf: function () {
return 17;
}
};
"object: " + obj; //"object: 17"
不管是对象的连接还是对象的相加,重载运算符”+”总是一致的行为。一般情况下,字符串的强制转换远比数字的强制转换更常见、更有用。最好避免使用valueOf()方法,除非对象是一个数字的抽象,并且obj.toString()能产生一个obj.valueOf()的字符串表示。
4. 真值运算
if,||,&&等逻辑运算符逻辑上需要布尔值作为操作参数,但实际上可以接受任何值。
大多数的JavaScript值都为真值,当然也是被隐式的转换为true,对于字符串和数字以外的其他对象,真值运算不会隐式的调用任何强制转换方法。
JavaScript中有7个假值:
false、0、-0、”“、NaN、null和undefined。其他所有值都为真值。
因此,使用真值运算检查函数参数或者对象的属性是否已定义不是绝对安全的。例如:
function point (x, y) {
if (!x) { x = 320; }
if (!y) { y = 240; }
return { x: x, y: y };
}
point(0, 0); // { x: 320, y: 240 }
解决方案:
使用严格的检查方式typeof;
(或者直接与undefined进行比较 if (x === undefined) { … })
function point (x, y) {
if (typeof x === "undefined") { x = 320; }
if (typeof y === "undefined") { y = 240; }
return { x: x, y: y };
}
point(); // { x: 320, y: 240 }
point(0, 0); // { x: 0, y: 0}