实现a==1&&a==2&&a==3为true
预置知识
在进行比较的时候,js解析会尝试先调用valueOf得到的值与之进行比较,再调用toString得到的返回值与之进行比较。
valueOf对不同类型处理的返回值:
js
obj.valueOf() // 返回它本身的值
arr.valueOf() // 返回它本身的值
str.valueOf() // 返回它本身的值
num.valueOf() // 返回它本身的值
boo.valueOf() // 返回它本身的值
date.valueOf() // 返回时间毫秒数
修改valueOf实现
js
let a = {
i: 1,
valueOf () {
return a.i++
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('Hello World!');
}
修改toString实现
js
let a = {
i: 1,
toString () {
return a.i++
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('Hello World!');
}
全等的解决方案
a === 1 && a ===2 && a===3 : Object.definProperty劫持
js
var value = 0; // window.value
Object.defineProperty(window, 'a', {
get: function() {
return value += 1
}
})
console.log(a===1 && a===2 && a===3) // true
注意:为啥要先声明value呢?
如果直接声明a,则使用Object.defineProperty(window, 'a')会报错(Cannot redefine property: a),因为声明在window上的属性configurable都为false
js
Object.getOwnPropertyDescriptor(window, 'a')
// {value: 0, writable: true, enumerable: true, configurable: false}
而未定义在window上的属性是可以劫持的
js
Object.getOwnPropertyDescriptor(window, 'value')
// undefined
普通对象的属性描述如下
js
let obj = {a: 1, b: 2}
Object.getOwnPropertyDescriptor(obj, 'a')
// {value: 1, writable: true, enumerable: true, configurable: true}
Proxy只能通过对象访问的方式进行代理达到全等的目的
js
let num = 0
let p = new Proxy({}, {
get: function(target, name) {
num++
return num
}
})
console.log(p.a === 1 && p.a === 2 && p.a === 3)