遇到一个懵逼的判断
if( a == 1 && a == 2 && a == 3 ) {
console.log(1);
}
咋一眼看上去,是不是觉着这是哪个傻逼写出来的,这不是永远不会成立的代码嘛…这就是我第一眼的感觉,疯了,但是它又是出自不可能出错的地方,那咋办,找问题呗…
在这里,其实有个误区,就是a的值,它不是同一时间为1、2、3的,它要有个运算,先来一个a1运算,再来一个a2运算,最后才到a==3运算,现在这么说是不是也有点懵逼呢,下来我详细说
在这里,我们看a的值哈,它就不可能是一个基础类型的值,因为基础类型的值即便是Number转换后与后面值比较,它也是永远不会变的啊,都是这个a的值必须是一个对象,前面有文中写比较运算符对象和数值做比较的时候,我也曾说过对象有个属性valueOf方法,当时我还挺懵逼对象和一个数值做比较,为啥啊,对象的valueof执行后就是对象自己啊,还要和一个值做比较,傻逼嘛,会一直是false的…现在想来,是我们己傻逼,人家这么弄必然有这么比较的原因啊…
先来看看这个valueof方法
let obj = {i:0}. //先来定义一个对象,并且有一个i:0的属性
然后,我们访问他的原型,
obj.__proto__.valueOf // ƒ valueOf() { [native code] }
可以看到是有一个valueOf的方法的,这个就是上面说的谁调用返回谁的那个方法啦
然后我们现在对比obj和数值吧,
obj ==1 // false
结果可想而知,肯定是false啊,这里有个默认转哈,就是对象和值做比较的时候会默认调用valueOf方法,代码上看不到,但是不代表它没有默默的在执行哈
其实它对比的时候会变成这个样子
obj.valueOf() == 1. //false
呃,是不是有点感觉了,默认情况下,valueOf是原生对象中的啊,那如果我们自己写一个valueOf呢,那执行的时候不就调用自己写的valueOf了嘛,我们让它返回啥它就返回啥,是不是这个意思,来看看吧
obj.valueOf = function(){ // 自己写一个valueOf方法,返回一个数值1
return 1;
}
此时,我们再来和1比较一下
obj == 1。// true
哎呦,和我们预期的一样,返回的值和右边的值做比较,返回true了,哈哈哈
那我们再回头看最初的判断哈 a1 && a2 && a==3
啥时候会为真呢,这里每一次比较都调用一次valueOf方法,那我们每次让它加1不就行了嘛,对吧,改造一下valueOf吧
obj.valueOf = function(){
this.i++; // 每次调用都自增1
return this.i;
}
打印obj来看看
{
i: 0,
valueOf(){
this.i++;
return this.i;
}
}
我们依次执行
obj == 1 // true
obj == 2 // true
obj == 3 // true
是不是一下就明白了,很哇塞吧
再来写一遍代码,巩固一下
let a = {i:0}
a.valueOf = function(){
this.i++;
return this.i;
}
if(a==1 && a==2 && a==3){
console.log("success")
}
打印success了,哈哈哈,问题解决!