[Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

“1.0e0”=={valueOf:function(){return true;}}

是值是多少?

[Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

这两个完全不同的值使用==运算符是相等的。为什么呢?请看《[Effective JavaScript笔记]第3条:当心隐式的强制转换

因为这个会在比较之前对两个值都进行隐式转换。字符串“1.0e0”被解析成1,而{valueOf:function(){return true;}}会通过调用自身的valueOf进行转化得到true,然后再转化为数字,得到1;

很容易使用强制转换完成一些工作。如,从一个WEB表单读取一个字段并与一个数字进行比较。

var today=new Date();

if(form.month.value == (today.getMonth()+1)&&

form.day.value==today.getDate()){

//….

}

但实际上,它只是显式地使用Number函数或者一元运算符+将值转换为数字。

var today=new Date();

if(+form.month.value == (today.getMonth()+1)&&

+form.day.value==today.getDate()){

//….

}

上面的这段代码更清晰地传达了在做什么样的转换。

更好的方法是用严格相等运算符

var today=new Date();

if(+form.month.value === (today.getMonth()+1)&&

+form.day.value===today.getDate()){

//….

}

注:当两个参数属于同一类型时,==和===没有区别。最好是用严格相等运算符===,可以清晰表达比较,并不涉及到转换。

==运算符针对不同类型参数的强制转换规则:

  • 1、null  ==    undefined     说明:不转换总是返回true
  • 2、null或undefined  ==   其他任何非null或undefined的类型   说明:不转换,总是返回false
  • 3、原始类型:string、number或boolean ==  Date对象  说明:将原始类型转换为数字,将Date对象转换为原始类型(优先尝试toString方法,再尝试valueOf方法)
  • 4、原始类型:string、number或boolean ==  非Date对象   说明: 将原始类型转换为数字,将非Date对象转换为原始类型(优先尝试valueOf方法,再尝试toString方法)
  • 5、原始类型:string、number或boolean ==  原始类型:string、number或boolean   说明:将原始类型转换为数字

==运算符将数据以不同的表现呈现出来,但计算机并不能真正地了解你的选择,因为有太多的数据表现形式,js需要知道你使用的是哪种。

例如:

[Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

这里的date转换成了“Mon May 09 2016 00:00:00 GMT+0800 (中国标准时间)”这种格式。

==不能推断和统一所有的数据格式。它需要你理解其微妙的强制转换规则。最好的策略是显式自定义应用程序转换的逻辑,并使用严格相等运算符===

function toYMD(date){
     var y=date.getYear()+1900,

m=date.getMonth()+1,

d=date.getDate();

return y+"/"+(m<10?"0"+m:m)+"/"+(d<10?"0"+d:d);
}

toYMD(date)==="2016/05/09";

显示地定义转换的逻辑能确保==运算符的强制转换规则,免除不得不查找或记住规则的麻烦。

提示:

  1. 当参数类型不同时,==运算符应用了一套难以理解的隐式强制转换规则。
  2. 使用===运算符,可以避免记住那些强制转换规则,使代码更清晰。
  3. 当比较不同类型的值时,最好显式地进行强制转换,使程序行为更清晰。
上一篇:eclipse 中 大小写切换:ctrl+shift+x 转为大写 ctrl+shift+y 转为小写


下一篇:bzoj 3781: 小B的询问 分块