如何让 if (a == 1 && a == 2) 条件成立?
面试速答(30 秒版 TL;DR)
- 利用
==会触发 对象 ToPrimitive,并且表达式会被求值两次(先比 1,再比 2)。 - 让
a每次 ToPrimitive 时返回不同的值(带副作用递增)即可。 - 最稳写法:实现
Symbol.toPrimitive(或valueOf)。
最小可运行答案(推荐背这个)
const a = {
i: 1,
[Symbol.toPrimitive]() {
return this.i++;
},
};
if (a == 1 && a == 2) {
console.log("ok");
}
为什么成立:
a == 1:a是对象,先 ToPrimitive,第一次返回1,成立。&&继续算右边:a == 2,第二次 ToPrimitive 返回2,成立。
备选写法:valueOf
let i = 0;
const a = {
valueOf() {
return ++i;
},
};
if (a == 1 && a == 2) {
console.log("ok");
}
解释口径:
- 普通对象 ToPrimitive(hint 为
"default"/"number")会优先尝试valueOf()。
常见追问
Q1:用 === 还能做到吗?
不行。=== 不做隐式类型转换,也就不会触发 ToPrimitive 去“变魔术”。
Q2:能不能用 getter 做到?
可以,但依赖运行环境和作用域规则,面试回答建议点到为止:
- “可以把
a设计成一个每次读取都会自增的 getter,但在模块/严格模式下直接访问未声明变量会报错;更通用的是用对象的 ToPrimitive 钩子。”
这题想考什么?
- 你是否理解
==会触发类型转换(尤其是对象 ToPrimitive)。 - 你是否理解表达式求值顺序与
&&的短路规则。