跳到主要内容

如何让 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 == 1a 是对象,先 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)。
  • 你是否理解表达式求值顺序与 && 的短路规则。