代理模式的定义:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
Proxy
在ES6中新增了一个API叫Proxy,Proxy 对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。
比较抽象,我用一句话总结就是:Proxy可以覆盖原有的方法,实现自定义的默认方法的功能。
基础语法
let p = new Proxy(target, handler);
/**
* target
* 用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)
* 一个对象,其属性是当执行一个操作时定义代理的行为的函数
**/
还是用一段代码来演示一下吧
let person = {
name: 'Tom',
age: 18
}
let newP = new Proxy(person, {
get(target, prop) {
if(!(prop in target)) {
return '没有对应的属性'
}
return target[prop]
}
})
console.log(person.name) // Tom
console.log(person.age) // 18
console.log(person.amount) // undefined
console.log(newP.name) // Tom
console.log(newP.age) // 18
console.log(newP.amount) // 没有对应的属性
通过以上代码,可以看到当访问newP对象中的属性时,实际上是调用了自定义的get方法,就是说我们自定义了一个get方法覆盖了原用的get方法。
Proxy的Handler
在Proxy中可以使用到的handler方法如下
handler.getPrototypeOf()
在读取代理对象的原型时触发该操作,比如在执行 Object.getPrototypeOf(proxy) 时。
handler.setPrototypeOf()
在设置代理对象的原型时触发该操作,比如在执行 Object.setPrototypeOf(proxy, null) 时。
handler.isExtensible()
在判断一个代理对象是否是可扩展时触发该操作,比如在执行 Object.isExtensible(proxy) 时。
handler.preventExtensions()
在让一个代理对象不可扩展时触发该操作,比如在执行 Object.preventExtensions(proxy) 时。
handler.getOwnPropertyDescriptor()
在获取代理对象某个属性的属性描述时触发该操作,比如在执行 Object.getOwnPropertyDescriptor(proxy, "foo") 时。
handler.defineProperty()
在定义代理对象某个属性时的属性描述时触发该操作,比如在执行 Object.defineProperty(proxy, "foo", {}) 时。
handler.has()
在判断代理对象是否拥有某个属性时触发该操作,比如在执行 "foo" in proxy 时。
handler.get()
在读取代理对象的某个属性时触发该操作,比如在执行 proxy.foo 时。
handler.set()
在给代理对象的某个属性赋值时触发该操作,比如在执行 proxy.foo = 1 时。
handler.deleteProperty()
在删除代理对象的某个属性时触发该操作,即使用 delete 运算符,比如在执行 delete proxy.foo 时。
handler.ownKeys()
Object.getOwnPropertyNames 和Object.getOwnPropertySymbols 的陷阱。
handler.apply()
函数调用操作的陷阱。
handler.construct()
new 运算符的陷阱。
Proxy的兼容性
参考
MDN