Proxy
2022年10月14日大约 6 分钟
概述
描述:用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等
语法:
const p = new Proxy(target, handler)
参数
- target:被 Proxy 包装的目标对象,可以是任何类型的对象,包括原生数组,函数,甚至另一个代理
- handler:一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理的行为
Proxy.revocable()
- 描述:创建一个可撤销的代理对象
- 语法:
Proxy.revocable(target, handler)
- 参数
- target:将用 Proxy 封装的目标对象。可以是任何类型的对象,包括原生数组,函数,甚至可以是另外一个代理对象
- handler:一个对象,其属性是一批可选的函数,这些函数定义了对应的操作被执行时代理的行为
- 返回值:一个包含了代理对象本身和它的撤销方法的可撤销 Proxy 对象
- proxy:表示新生成的代理对象本身,和用一般方式
new Proxy(target, handler)
创建的代理对象没什么不同,只是它可以被撤销掉 - revoke:撤销方法,调用的时候不需要加任何参数,就可以撤销掉和它一起生成的那个代理对象
- proxy:表示新生成的代理对象本身,和用一般方式
- 注意:一旦某个代理对象被撤销,它将变得几乎完全不可调用,在它身上执行任何的可代理操作都会抛出 TypeError 异常(注意,可代理操作一共有 14 种,执行这 14 种操作以外的操作不会抛出异常)
handler.get()
- 描述:拦截对象读取属性的操作
- 参数
- target:目标对象
- property:被获取的属性名
- property:Proxy 或者继承 Proxy 的对象
- 返回值:可以返回任何值
- 拦截操作
- 访问属性
- 访问原型链上的属性
Reflect.get()
- 注意:如果违背了以下的约束,proxy 会抛出 TypeError
- 如果要访问的目标属性是不可写以及不可配置的,则返回的值必须与该目标属性的值相同
- 如果要访问的目标属性没有配置访问方法,即 get 方法是 undefined 的,则返回值必须为 undefined
handler.set()
- 描述:拦截对象设置属性值的操作
- 参数
- target:目标对象
- property:将被设置的属性名或 Symbol
- value:新属性值
- property:Proxy 或者继承 Proxy 的对象
- 返回值:返回一个布尔值
- 返回 true 代表属性设置成功
- 在严格模式下,如果 set() 方法返回 false,那么会抛出一个 TypeError 异常
- 拦截操作
- 设置属性值
- 设置原型链上的属性值
Reflect.set()
- 注意:如果违背了以下的约束,proxy 会抛出 TypeError
- 若目标属性是一个不可写及不可配置的数据属性,则不能改变它的值
- 如果目标属性没有配置存储方法,即 [[Set]] 属性的是 undefined,则不能设置它的值
- 在严格模式下,如果 set() 方法返回 false,那么也会抛出一个 TypeError 异常
handler.has()
- 描述:针对
in
操作符的代理方法 - 参数
- target:目标对象
- prop:需要检查是否存在的属性
- 返回值:返回一个 boolean 属性的值
- 拦截操作
- 属性查询:
foo in proxy
- 继承属性查询:
foo in Object.create(proxy)
- with 检查
with(proxy) { (foo); }
Reflect.has()
- 属性查询:
- 注意:如果违背了以下的约束,proxy 会抛出 TypeError
- 如果目标对象的某一属性本身不可被配置,则该属性不能够被代理隐藏
- 如果目标对象为不可扩展对象,则该对象的属性不能够被代理隐藏
handler.ownKeys()
- 描述:用于拦截
Reflect.ownKeys()
- 参数
- target:目标对象
- 返回值:必须返回一个可枚举对象
- 拦截操作
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.keys()
Reflect.ownKeys()
- 注意:如果违背了以下的约束,proxy 会抛出 TypeError
ownKeys
的结果必须是一个数组- 数组的元素类型要么是一个 String ,要么是一个 Symbol
- 结果列表必须包含目标对象的所有不可配置(non-configurable )、自有(own)属性的key
- 如果目标对象不可扩展,那么结果列表必须包含目标对象的所有自有(own)属性的key,不能有其它值
handler.defineProperty()
- 描述:用于拦截对对象的
Object.defineProperty()
操作 - 参数
- target:目标对象
- property:待检索其描述的属性名
- descriptor:待定义或修改的属性的描述符
- 返回值:必须以一个 Boolean 返回,表示定义该属性的操作成功与否
- 拦截操作
Object.defineProperty()
Reflect.defineProperty()
- 注意:如果违背了以下的约束,proxy 会抛出 TypeError
- 如果目标对象不可扩展, 将不能添加属性
- 不能添加或者修改一个属性为不可配置的,如果它不作为一个目标对象的不可配置的属性存在的话
- 如果目标对象存在一个对应的可配置属性,这个属性可能不会是不可配置的
- 如果一个属性在目标对象中存在对应的属性,那么
Object.defineProperty(target, prop, descriptor)
将不会抛出异常 - 在严格模式下, false 作为
handler.defineProperty
方法的返回值的话将会抛出 TypeError 异常
handler.deleteProperty()
- 描述:用于拦截对对象属性的
delete
操作 - 参数
- target:目标对象
- property:待删除的属性名
- 返回值:必须返回一个
Boolean
类型的值,表示了该属性是否被成功删除 - 拦截操作
- 删除属性
delete proxy[foo]
和delete proxy.foo
Reflect.deleteProperty()
- 删除属性
- 注意:如果违背了以下的约束,proxy 会抛出 TypeError
- 如果目标对象的属性是不可配置的,那么该属性不能被删除
handler.apply()
- 描述:用于拦截函数的调用
- 参数
- target:目标对象(函数)
- thisArg:被调用时的上下文对象
- argumentsList:被调用时的参数数组
- 返回值:可以返回任何值
- 拦截操作
proxy(...args)
Function.prototype.apply()
和Function.prototype.call()
Reflect.apply()
- 注意:如果违背了以下的约束,proxy 会抛出 TypeError
- target必须是可被调用的。也就是说,它必须是一个函数对象
handler.construct()
- 描述:用于拦截
new
操作符 - 参数
- target:目标对象(函数)
- argumentsList:constructor 的参数列表
- newTarget:最初被调用的构造函数
- 返回值:必须返回一个对象
- 拦截操作
new proxy(...args)
Reflect.construct()
- 注意:如果违背了以下的约束,proxy 会抛出 TypeError
- 必须返回一个对象