一、语法
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)