-
Notifications
You must be signed in to change notification settings - Fork 0
Day04 如何让 (a == 1 && a == 2 && a == 3) 的值为true?
x == y的比较(其中x和y是值)会返回true或false。 比较执行过程如下:
-
x和y类型相同:返回x === y
-
一个是null,一个undefined:返回true
-
一个是number一个是string:返回number == ToNumber(string)
-
一个是bigint,一个是string: 返回StringToBigInt(string) 结果是 NaN ?false :bigint == StringToBigInt(string)
-
如果类型是Boolean, 执行转换 **ToNumber(boolean)**后再比较 .
-
一个是String, Number, BigInt, Symbol,另一个是Object, 对object执行转换**ToPrimitive(object)**后再比较
-
一个是Number, 另一个是BigInt:
- 如果x或y等于 NaN, +∞, 或-∞, 返回false.
- 比较数值,相等返回true
-
其他任何情况都返回false.
要满足a == 1 && a == 2 && a == 3,假设a是原始类型:
-
number,找不到满足条件的number,不成立
-
bigint,根据上面原理的第7条,会直接比较值,找不到满足条件的bigint,不成立
-
string,根据上面原理的第3条,会转换成number,找不到满足条件的string,不成立
-
boolean,根据上面原理的第5条,会被转成number再比较,结果是0或1,不成立
-
null,根据上面原理的第8条,结果是false,不成立
-
undefined,同上
-
symbol,同上
所以a不可能是原始类型,只能是object类型。
根据==比较原理的第6条,对object执行ToPrimitive(object)
,转换为原始值后再比较
ECMA种定义的ToPrimitive(object)
的执行顺序:
- 如果
obj[Symbol.toPrimitive]
接口存在,则调用该接口 - 如果object上的自身方法
valueOf
存在,则调用valueOf - 如果object上的自身方法
toString
存在,则调用toString - 上溯对象原型链查找valueOf和toString方法,根据不同原型,valueOf和toString优先级不同
- date/string类型
toString>valueOf
- number类型
valueOf>toString
- ...
- date/string类型
因此可以通过更改对象的获取原始值的方法,达到满足a == 1 && a == 2 && a == 3
的目的
Symbol.toPrimitive
valueOf
toString
let a = {
[Symbol.toPrimitive]: (function(hint) {
let i = 1;
//闭包的特性之一:i 不会被回收
return function() {
return i++;
}
})()
}
console.log(a == 1 && a == 2 && a == 3); //true
let a = {
valueOf: (function() {
let i = 1;
//闭包的特性之一:i 不会被回收
return function() {
return i++;
}
})()
}
console.log(a == 1 && a == 2 && a == 3); //true
- Object.defineProperty
- Proxy
let i = 1;
Object.defineProperty(window, 'a', {
get: function() {
return i++;
}
});
console.log(a == 1 && a == 2 && a == 3); //true
let a = new Proxy({}, {
i: 1,
get: function () {
return () => this.i++;
}
});
console.log(a == 1 && a == 2 && a == 3); // true
let i = 0;
with ({
get a() {
return ++i;
}
}) {
console.log(a == 1 && a == 2 && a == 3); //true
}