ES6 中的 Proxy 与 Reflect

56 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 17 天,点击查看活动详情

Proxy 和 Reflect 都是 ES6 中新增的属性。Proxy 意为代理,Reflect 意为反射。它们都是为了操作对象而引入的。

Proxy

如果熟悉 Vue3 的响应式原理,就会知道 Proxy 的用途。在 Vue2 中使用 Object.defineProperty() 来进行数据劫持,它不直接操作数据,而是对数据进行代理。而 Vue3 中使用 Proxy 正是为了监听数组和对象的变化。

Proxy 的形式:

Proxy(target, handler)
let target = {
    name: 'user',
    msg: 'hello'
}

let proxy = new Proxy(target, {
    get: function(target, key) {
        console.log('获取数据 ', key);
        return target[key]; // 不是target.key
    },
    set: function(target, key, value) {
        console.log('设置数据 ', key);
        target[key] = value;
    }
})

对于获取数据和设置数据的输出,可以观察到如下效果:

  • 输出或是使用数据的时候,执行的是 handler.get
  • 为数据赋值的时候,执行的是 handler.set
console.log(proxy.name)    // 实际执行 handler.get
proxy.msg = 'hi' // 实际执行 handler.set

运行结果:

image.png

console.log(proxy.msg)

运行结果:

image.png

Reflect

let obj = {}
console.log(Reflect.__proto__ === Object.prototype); 
console.log(Reflect.__proto__ === obj.__proto__);

image.png

通过上面关于原型的比较,可以看到 Reflect 的原型是 Object。接下来再输出 Object 的原型,可以看到一些我们比较熟悉的内部方法:

image.png

将其对应到 Reflect 对象上,我们可以通过 Reflect 来使用这些方法。有如下特点:

  • Reflect 的方法与 Proxy 是对应的,只要是 Proxy 中存在的方法,Reflect中也可以找到对应方法
  • 修改某些 Object 方法的返回结果,使其更加合理(比如 Reflect.defineProperty 遇到错误可以返回false,而 Object.defineProperty 会报错)
  • Reflect 是一种函数行为,而 Object 属于命令式语句

Reflect的属性和方法都是静态的,其形式如下:

Reflect.get(target, name, receiver)
let info = {
    name: "user",
    count: 1,
    set update(val){
        return this.count = val;
    }
}
console.log(info.count);
Reflect.set(info, 'count', 100);
console.log(info.count);

运行结果:

image.png