Appearance
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
2
3
这个是经典问题了,这里给出一种方法实例,其他方法的思想都和下面这种方法差不多。这里利用了 ==
在对象与其他类型比较会触发 隐式转换 的原理,重写 toString
或者 valueOf
方法。
js
let x = {
value: 1,
toString() {
return this.value++
}
}
1
2
3
4
5
6
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
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
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
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
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
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
2
3
4
5
6
7
8
9
10
11
12
13