Proxy和Reflect详解
Proxy类基本使用
在ES6中,新增了一个Proxy类,这个类从名字就可以看出来,是用于帮助我们创建一个代理的,也就是说,如果我们希望监听一个对象的相关操作,那么我们可以先创建一个代理对象(Proxy对象);之后对该对象的所有操作,都通过代理对象来完成,代理对象可以监听我们想要对原对象进行哪些操作。
创建代理首先需要new Proxy对象,并且传入需要侦听的对象target,以及一个处理对象handler,const p = new Proxy(target, handler)
;我们之后的操作都是直接对Proxy的操作,而不是原有的对象,因为我们需要在handler里面进行侦听。
//示例
const obj = {
name:'why',
age:18
}
// p对象就成为了obj的代理对象,对p对象做任何操作都能监听到变化
const p = new Proxy(obj,{
get:function(target,key){
console.log(`访问属性${key}`);
return target[key]
},
set:function(target,key,newVal){
console.log(`修改属性${key}`);
target[key] = newVal
}
})
Proxy常见捕获器
proxy共有13种捕获器
1.
handler.get()
属性读取操作的捕捉器
2.handler.set()
属性设置操作的捕捉器
3.handler.has()
in 操作符的捕捉器
4.handler.deleteProperty()
delete 操作符的捕捉器
5.handler.getPrototypeOf()
Object.getPrototypeOf 方法的捕捉器(获取原型)
6.handler.setPrototypeOf()
Object.setPrototypeOf 方法的捕捉器(设置原型)
7.handler.isExtensible()
Object.isExtensible 方法的捕捉器(判断是否可以新增属性)
8.handler.preventExtensions()
Object.preventExtensions 方法的捕捉器(防止对象新增属性)
9.handler.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor 方法的捕捉器(获取属性描述符)
10.handler.defineProperty()
Object.defineProperty 方法的捕捉器
11.handler.ownKeys()
Object.getOwnPropertyNames方法和Object.getOwnPropertysymbols 方法的捕捉器
12.handler.apply()
函数调用操作的捕捉器
13.handler.construct()
new 操作符的捕捉器
Reflect介绍和作用
1.Reflect也是ES6新增的一个API,它是一个对象,字面的意思是反射。
2.那么这个Reflect有什么用呢?
- 它主要提供了很多操作JavaScript对象的方法,有点像Object中操作对象的方法;
- 比如Reflect.getPrototypeOf(target)类似于 Object.getPrototypeOf();
- 比如Reflect.defineProperty(target, propertyKey, attributes)类似于Object.defineProperty();
3.如果我们有Object可以做这些操作,那么为什么还需要有Reflect这样的新增对象呢?
- 这是因为在早期的ECMA规范中没有考虑到这种对 对象本身 的操作如何设计会更加规范,所以将这些API放到了Object上面;
- 但是Object作为一个构造函数,这些操作实际上放到它身上并不合适;
- 另外还包含一些类似于 in、delete操作符,让JS看起来是会有一些奇怪的;
- 所以在ES6中新增了Reflect,让我们这些操作都集中到了Reflect对象上;
- 另外在使用Proxy时,可以做到不操作原对象;
Reflect方法:
和Proxy的13种所对应,如Reflect.get()…
Reflect的基本使用
1.基本使用
//示例
const obj = {
name:'why',
age:18
}
// p对象就成为了obj的代理对象,对p对象做任何操作都能监听到变化
const p = new Proxy(obj,{
get(target,key,,receiver){
console.log(`访问属性${key}`);
return Reflect.get(target,key,receiver)
},
set(target,key,newVal,receiver){
console.log(`修改属性${key}`);
const success = Reflect.set(target,key,newVal,receiver)
if(!success){
throw new Error(`set ${key} failure`)
}
}
})
2.使用Reflect的好处:
- 代理则象的目的:不再直接操作原对象
- Reflect的方法有返回Boolean值,可以判断本次操作是否成功
- 最后一个参数
receiver参数
就是外层Proxy对象,它可以决定对泉访问器setter/getter的this指向- Reflect所做操作都是直接对 对象的基本操作,而obj.name这种是经过一系列操作,最终也是调用的对象的基本操作
[[ GET ]]