5.避免对混合类型使用 == 运算符
2017-12-12 本文已影响0人
Somnusochi
"1.0e0" == { valueOf:function() { return true; } }; // true
在比较之前它们都被转换为数字,字符串"1.0e0"
被解析为数字1,而匿名对象也通过调用自身的valueOf
方法得到结果true,然后再转换为数字,得到1。
很容易使用这些强制转换完成一些工作。
var today = new Date();
if (form.month.value == (today.getMonth() + 1) && form.day.value == today.getDate()){
// happy birthday!
// ...
}
// 等效于
var today = new Date();
if (+form.month.value == (today.getMonth() + 1) && +form.day.value == today.getDate()){
// happy birthday!
// ...
}
// 等效于
var today = new Date();
if (+form.month.value == (today.getMonth() + 1) && +form.day.value == today.getDate()){
// happy birthday!
// ...
}
// 当两个参数属于同一类型时,==和===运算符的行为是没有区别的,如果参数属于同一类型,那么==和===运算符可以互换,但最好使用严格相等运算符。
== 运算符的强制转换规则
参数类型1 | 参数类型2 | 强制转换 |
---|---|---|
null | undefined | 不转换,总是返回true |
null 或 undefined | 其他任何非 null 或 undefined 的类型 | 不转换,总是返回 false |
string、number 或 boolean | Date 对象 | 将原始类型转换为数字;将 Date 对象转换为原始类型(优先尝试 toString 方法,再尝试 valueOf 方法) |
string、number 或 boolean | 非 Date 对象 | 将原始类型转换为数字;将非 Date 对象转换为原始类型(优先尝试用 valueOf 方法,再尝试 toString 方法) |
string、number 或 boolean | string、number 或 boolean | 将原始类型转换为数字 |
== 运算符并不能推断和统一所有的数据格式
var date = new Date("2017/12/12");
data == "2017/12/12"; // false
date.toString(); // "Tue Dec 12 2017 00:00:00 GMT+0800 (CST)"
更好的策略是显式自定义应用程序转换的逻辑,并使用严格相等运算符
function toYMD(date) {
var y = date.getYear() + 1900, // 年从1900开始计数
m = date.getMonth() + 1, // 月从0开始计数
d = date.getDate();
return y + "/" + (m < 10 ? "0" + m : m) + "/" + (d < 10 ? "0" + d : d);
}
toYMD(date) === "2017/12/12"; // true
// 显式地定义转换的逻辑能确保你不会混淆 == 运算符的强制转换规则,而且免除了读者不得不查找或记住这些规则的麻烦。
提示
- 当参数类型不同时,
==
运算符应用了一套难以理解的隐式强制转换规则。 - 使用 === 运算符,使读者不需要涉及任何隐式强制转换就能明白你的比较运算。
- 当比较不同类型的值时,使用你自己的显式强制转换使程序的行为更清晰。