Skip to content

01. == 与 === 问题

1. x == 1 && x == 2 && x == 3

如何定义 x,使得下列代码的 Hello World 成功输出?

js
if (x == 1 && x == 2 && x == 3) {
  console.log('Hello World')
}
1
2
3

这个是经典问题了,这里给出一种方法实例,其他方法的思想都和下面这种方法差不多。这里利用了 == 在对象与其他类型比较会触发 隐式转换 的原理,重写 toString 或者 valueOf 方法。

js
let x = {
  value: 1,
  toString() {
    return this.value++
  }
}
1
2
3
4
5
6

TIP

如果你还不了解 == 的比较原理,请移步 MDN 文档:MDN ==

如果你对其他解法感兴趣,请移步我的掘金:a==1 && a==2 && a==3 的三种解法

2. x !== x

如何定义 x,使得下列代码的 Hello World 成功输出?

js
if (x !== x) {
  console.log('Hello World')
}
1
2
3

解法1

相信大家都想出了 x = NaN 这个方法,因为 NaN 和任何值使用 === 比较,返回的都是 false,因此 NaN !=== NaN 返回 true

解法2

我们知道 === 不会触发隐式转换,那么就必须劫持【获取 x 的值】这个行为,因为比较的过程中就是 获取值,然后进行比较,自然而然就想到了 getter。这里的 x 是在全局环境下直接获取然后比较的(不是 obj.x === obj.x 这种),那我们就能想到劫持全局环境下的属性,全局环境是指:

  • 浏览器中:window
  • 浏览器中:global 对象

一切尽在代码之中:

js
function getGlobal() {
  return this
}

Reflect.defineProperty(getGlobal(), 'x', {
  get() {
    return Math.random() // 每次获取 x 都返回一个随机值
  }
})

if (x !== x) {
  console.log('Hello World')
}
1
2
3
4
5
6
7
8
9
10
11
12
13

3. x === x + 1

如何定义 x,使得下列代码的 Hello World 成功输出?

js
if (x === x + 1) {
  console.log('Hello World')
}
1
2
3

这道题和上一道异曲同工,第二次获取令其减一即可。

js
function getGlobal() {
  return this
}
let y = 0
Reflect.defineProperty(getGlobal(), 'x', {
  get() {
    return y--
  }
})

if (x === x + 1) {
  console.log('Hello World')
}
1
2
3
4
5
6
7
8
9
10
11
12
13

4. x === 1 && x === 2 && x === 3

如何定义 x,使得下列代码的 Hello World 成功输出?

js
if (x === 1 && x === 2 && x === 3) {
  console.log('Hello World')
}
1
2
3

同样的,劫持全局环境下的 x

js
function getGlobal() {
  return this
}
let y = 1
Reflect.defineProperty(getGlobal(), 'x', {
  get() {
    return y++
  }
})

if (x === 1 && x === 2 && x === 3) {
  console.log('Hello World')
}
1
2
3
4
5
6
7
8
9
10
11
12
13