开启掘金成长之旅!这是我参与「掘金日新计划 · 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
运行结果:
console.log(proxy.msg)
运行结果:
Reflect
let obj = {}
console.log(Reflect.__proto__ === Object.prototype);
console.log(Reflect.__proto__ === obj.__proto__);
通过上面关于原型的比较,可以看到 Reflect 的原型是 Object。接下来再输出 Object 的原型,可以看到一些我们比较熟悉的内部方法:
将其对应到 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);
运行结果: