ECMAScript 6 Proxy

Proxy主要用于定义基本操作的自定义行为,包括属性查找、赋值、枚举、函数调用等。

Proxy(target, handler)构造函数接收两个参数,target为被代理的对象,handler为处理器对象,用来自定义代理对象的各种操作。目前,一共有 13 种可代理操作:

get(target, propery, receiver)

在读取代理对象的某个属性时触发该操作,比如在执行 proxy.foo 时。

const target = {
    name: 'aaa',
};
const targetProxy = new Proxy(target, {
    // 在读取代理对象的某个属性时触发该操作
    get(target, property, receiver) {
        return target[property] || null;
    }
});

targetProxy.name === target.name; // true
targetProxy.x === null; // true

通过proxyget拦截可以轻松实现 readOnly 和单例模式。

set(target, propKey, value, receiver)

在给代理对象的某个属性赋值时触发该操作,比如在执行 proxy.foo = 1时。

可以通过设置代理对象的set处理器轻松的根据需求对对象的写入进行控制。

deleteProperty(target, property)

在删除代理对象的某个属性时触发该操作,比如在执行 delete proxy.foo时。

defineProperty(target, property, descriptor)

在定义代理对象某个属性时的属性描述时触发该操作,如Object.defineProperty()Object.defineProperties()

  • 如果目标对象不可扩展, 将不能添加属性;

  • 不能添加或者修改一个属性为不可配置的,如果它不作为一个目标对象的不可配置的属性存在的话;

  • 如果目标对象存在一个对应的可配置属性,这个属性可能不会是不可配置的;

  • 如果一个属性在目标对象中存在对应的属性,那么Object.defineProperty(target, prop, descriptor)将不会抛出异常;

  • 在严格模式下,false作为handler.defineProperty方法的返回值的话将会抛出 TypeError

has(target, property)

在判断代理对象是否拥有某个属性时触发该操作,如in运算符。

  • 如果目标对象的某一属性本身不可被配置,则该属性不能够被代理隐藏

  • 如果目标对象为不可扩展对象,则该对象的属性不能够被代理隐藏

has拦截对for...in循环不生效。

ownKeys(target)

在获取代理对象的所有属性键时触发该操作,如在 Object.getOwnPropertyNames(obj)时。

  • 结果必须是一个数组;

  • 数组的元素类型只能是StringSymbol

  • 结果列表必须包含目标对象的所有不可配置(non-configurable )、自有(own)属性的key;

  • 如果目标对象不可扩展,那么结果列表必须包含目标对象的所有自有(own)属性的key,不能有其它值。

getOwnPropertyDescriptor(target, property)

在获取代理对象某个属性的属性描述时触发该操作,如:Object.getOwnPropertyDescriptor(obj, prop)

  • 必须返回一个objectundefined

  • 如果属性作为目标对象的不可配置的属性存在,则该属性无法报告为不存在

  • 如果属性作为目标对象的属性存在,并且目标对象不可扩展,则该属性无法报告为不存在

  • 如果属性不存在作为目标对象的属性,并且目标对象不可扩展,则不能将其报告为存在

  • 属性不能被报告为不可配置,如果它不作为目标对象的自身属性存在,或者作为目标对象的可配置的属性存在

  • Object.getOwnPropertyDescriptor(target)的结果可以使用Object.defineProperty应用于目标对象,也不会抛出异常

apply(target, context, args)

在调用一个目标对象为函数的代理对象时触发该操作,比如 proxy()proxy.call()proxy.apply()

target必须可被调用

construct (target, args, newTarget)

target必须是一个合法的 constructor ,并且必须返回一个对象

getPrototypeOf(proxy)

在读取代理对象的原型时触发该操作,比如在执行Object.getPrototypeOf(proxy)时。

当同时触发处理器getgetPrototypeOf操作时,get的优先级更高。

setPrototypeOf(target, proto)

在设置代理对象的原型时触发该操作,如:Object.setPrototypeOf(proxy)。如果返回false会抛出个TypeError异常。

如果target不可扩展,原型参数必须与Object.getPrototypeOf()的值相同。

isExtensible(target)

在判断一个代理对象是否是可扩展时触发该操作,如:Object.isExetensible(proxy)时。

Object.isExtensible(proxy) 必须返回与Object.isExtensible(target)相同的值。

preventExtensions(target)

在让一个代理对象不可扩展时触发该操作,比如在执行Object.preventExtensions(proxy)时。如果返回false会抛出个TypeError异常。

如果Object.isExtensible(proxy)falseObject.preventExtensions(proxy)只能返回true

最后更新于