Skip to content

实现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)