如何使 a == 1 && a == 2 && a == 3 为 true
问题描述
在 JavaScript 中,如何使
(a == 1 && a == 2 && a == 3)
返回true
?
解决方案
方案一:使用 getter 存储器
var n = 1
Object.defineProperty(globalThis, 'a', {
get() {
return n++
},
})
a == 1 && a == 2 && a == 3 // true
a === 1 && a === 2 && a === 3 // true
INFO
使用 getter 存储器的方式,也就是以全局变量 n
存储一个值,每次调用的时候都使 n = n + 1
。
valueOf()
或 toString()
方法
方案二:重写对象的 const a = {
value: 1,
valueOf() {
return this.value++
},
}
a == 1 && a == 2 && a == 3 // true
const a = {
value: 1,
toString() {
return a.value++
},
}
a == 1 && a == 2 && a == 3 // true
这里的 valueOf()/toString()
为什么会被调用 ?
原因参考如下:
- 如果一个是
null
,一个是undefined
,则它们相等。 - 如果一个是数字,一个是字符串,先将字符串转换成数字,然后使用转换后的值进行比较。
- 如果其中的一个值为
true
,则转换成 1 再进行比较;如果其中一个值为false
,这转换成0
再进行比较。 - 如果一个值是对象,另一个值是数字或者字符串,则将对象转换成原始值再进行比较。转换成字符串时,会先调用
toString()
,如果没有toString()
方法或者返回的不是一个原始值,则再调用valueOf()
,如果还是不存在或者返回不是原始值,则会抛出一个类型错误的异常。返回的原始值会被转换成字符串;如果转换成数字时,也是类似的,不过是会先调用valueOf()
,再调用toString()
,返回的原始值会被转换成数字。 - 其他不同类型之间的比较均不相等。
所以在这里使用 a
与这些字符进行比较时会被转换成数字,此时会默认调用字符串的 valueOf()/toString()
方法,我们将这个方法进行重写,用于拦截处理 a
的值。
方案三:Proxy
const a = new Proxy(
{ i: 0 },
{
get(target, name) {
return name === Symbol.toPrimitive ? () => ++target.i : target[name]
},
}
)
a == 1 && a == 2 && a == 3 // true
- 问题描述
- 解决方案
- 方案一:使用 getter 存储器
- 方案二:重写对象的 valueOf() 或 toString() 方法
- 方案三:Proxy