怎么让(a == 1 && a == 2 && a == 3)为true

144 阅读2分钟

今天群里发了一个问题:怎么让(a == 1 && a == 2 && a == 3)为true,群友给出了几个答案,感觉挺有意思的,在这里分享一下。

思路1、隐式转换

首先想到的就是利用 == 时会出现隐式转换来解决这个问题,复杂类型数据进行隐式转换成number时会先使用valueOf()获取原始值,如果原始值不是number类型则会使用toString()转换为字符串,此时就有两个解决方案:valueOf与toString

valueOf

const a = {
	n : 1,
    valueOf:() => {
    	return a.n++
    }
}
console.log(a == 1 &&  a == 2 && a == 3); //true

toString

const a = [1,2,3];
a.toString = a.shift;
console.log(a == 1 &&  a == 2 && a == 3); //true

思路2、Symbol.toPrimitive

当对象被转化为原始值时会触发Symbol.toPrimitive函数,此时可以对a进行修改

let n = 1;
const a = {
  [Symbol.toPrimitive](hint) {
    return n++;
  },
};
console.log(a == 1 && a == 2 && a == 3); //true

思路3、Object.definedProperty

在a进行比较的时候我们可以利用Object.definedProperty进行数据劫持来实现相应功能,此时(a === 1 && a ===2 && a === 3)也为true

let n = 1;
Object.definedProperty(window, 'a',{
	get: function(){
    	return n++;
    }
})
console.log(a == 1 && a ==2 && a == 3);

以上就是让(a == 1 && a == 2 && a == 3)为true的几个方法了,在总结这几个方法的时候也遇到了几个问题

1、Proxy

想到用Object.definedProperty来处理时也想到了Proxy,但是在实际操作时发与Object.definedProperty相比proxy需要一个实例来劫持window的属性,而又不能将这个实例设为window,所以只能实现(proxy.a == 1 && proxy.a ==2 && proxy.a == 3)

2、用Symbol.toPrimitive时发现了这个问题

查阅资料之后了解到Symbol.toPrimitive是一个内置的 Symbol 值,是作为对象的函数值属性存在,它的执行上下文里没有n这个在a对象内的值,所以需要将n放在外面让Symbol.toPrimitive获取到。