一、语法
1 | var p = new Proxy(target, handler); |
传参说明
target:使用Proxy包装的目标对象,它可以是任何类型的对象,包括数组、函数或甚至另一个proxy对象handler:一个对象,其属性是在对其执行操作时定义代理行为的函数
对象代理
1 | var obj = new Proxy({}, { |
注:
- 要使得
Proxy起作用,必须针对Proxy实例进行操作,而不是针对目标对象进行操作 - 如果
handler没有设置任何拦截,那就等同于直接通向原对象 - Proxy 实例可以作为其他对象的原型对象
函数代理
1 | var handler = { |
注:Proxy比Object.defineProperty 的功能更强大。Vue的作者宣称将在Vue3.0版本后加入Proxy从而代替Object.defineProperty 。
二、创建可撤销的Proxy对象
1 | // 创建 |
返回对象参数说明
proxy:表示新生成的代理对象本身,和用一般方式new Proxy(target, handler)创建的代理对象没什么不同,只是它可以被撤销掉。revoke:撤销方法,调用的时候不需要加任何参数,就可以撤销掉和它一起生成的那个代理对象。
注:一旦某个代理对象被撤销,它将变的几乎完全不可用,永远不可能恢复到原来的状态,在它身上执行任何的可代理操作都会抛出 TypeError 异常。同时和它关联的目标对象以及处理器对象将有可能被垃圾回收掉。
1 | var revocable = Proxy.revocable({}, { |
三、13 种Proxy代理操作
- get(target, propKey, receiver):拦截对象属性的读取,比如
proxy.foo和proxy['foo']
- set(target, propKey, value, receiver):拦截对象属性的设置,比如
proxy.foo = v或proxy['foo'] = v,返回一个布尔值
- has(target, propKey):拦截
propKey in proxy的操作,返回一个布尔值
- deleteProperty(target, propKey):拦截
delete proxy[propKey]的操作,返回一个布尔值
- ownKeys(target):拦截
Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性
- getOwnPropertyDescriptor(target, propKey):拦截
Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象
- defineProperty(target, propKey, propDesc):拦截
Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值
- preventExtensions(target):拦截
Object.preventExtensions(proxy),返回一个布尔值
- getPrototypeOf(target):拦截
Object.getPrototypeOf(proxy),返回一个对象
- isExtensible(target):拦截
Object.isExtensible(proxy),返回一个布尔值
- setPrototypeOf(target, proto):拦截
Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截
- apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如
proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)
- construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如
new proxy(...args)