跳至主要內容

Proxy

Yang大约 6 分钟

Proxyopen in new window


概述

  • 描述:用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等

  • 语法:const p = new Proxy(target, handler)

  • 参数

    • target:被 Proxy 包装的目标对象,可以是任何类型的对象,包括原生数组,函数,甚至另一个代理
    • handler:一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理的行为

Proxy.revocable()open in new window

  • 描述:创建一个可撤销的代理对象
  • 语法:Proxy.revocable(target, handler)
  • 参数
    • target:将用 Proxy 封装的目标对象。可以是任何类型的对象,包括原生数组,函数,甚至可以是另外一个代理对象
    • handler:一个对象,其属性是一批可选的函数,这些函数定义了对应的操作被执行时代理的行为
  • 返回值:一个包含了代理对象本身和它的撤销方法的可撤销 Proxy 对象
    • proxy:表示新生成的代理对象本身,和用一般方式 new Proxy(target, handler) 创建的代理对象没什么不同,只是它可以被撤销掉
    • revoke:撤销方法,调用的时候不需要加任何参数,就可以撤销掉和它一起生成的那个代理对象
  • 注意:一旦某个代理对象被撤销,它将变得几乎完全不可调用,在它身上执行任何的可代理操作都会抛出 TypeError 异常(注意,可代理操作一共有 14 种,执行这 14 种操作以外的操作不会抛出异常)

handler.get()open in new window

  • 描述:拦截对象读取属性的操作
  • 参数
    • target:目标对象
    • property:被获取的属性名
    • property:Proxy 或者继承 Proxy 的对象
  • 返回值:可以返回任何值
  • 拦截操作
    • 访问属性
    • 访问原型链上的属性
    • Reflect.get()
  • 注意:如果违背了以下的约束,proxy 会抛出 TypeError
    • 如果要访问的目标属性是不可写以及不可配置的,则返回的值必须与该目标属性的值相同
    • 如果要访问的目标属性没有配置访问方法,即 get 方法是 undefined 的,则返回值必须为 undefined

handler.set()open in new window

  • 描述:拦截对象设置属性值的操作
  • 参数
    • target:目标对象
    • property:将被设置的属性名或 Symbol
    • value:新属性值
    • property:Proxy 或者继承 Proxy 的对象
  • 返回值:返回一个布尔值
    • 返回 true 代表属性设置成功
    • 在严格模式下,如果 set() 方法返回 false,那么会抛出一个 TypeError 异常
  • 拦截操作
    • 设置属性值
    • 设置原型链上的属性值
    • Reflect.set()
  • 注意:如果违背了以下的约束,proxy 会抛出 TypeError
    • 若目标属性是一个不可写及不可配置的数据属性,则不能改变它的值
    • 如果目标属性没有配置存储方法,即 [[Set]] 属性的是 undefined,则不能设置它的值
    • 在严格模式下,如果 set() 方法返回 false,那么也会抛出一个 TypeError 异常

handler.has()open in new window

  • 描述:针对 in 操作符的代理方法
  • 参数
    • target:目标对象
    • prop:需要检查是否存在的属性
  • 返回值:返回一个 boolean 属性的值
  • 拦截操作
    • 属性查询: foo in proxy
    • 继承属性查询: foo in Object.create(proxy)
    • with 检查 with(proxy) { (foo); }
    • Reflect.has()
  • 注意:如果违背了以下的约束,proxy 会抛出 TypeError
    • 如果目标对象的某一属性本身不可被配置,则该属性不能够被代理隐藏
    • 如果目标对象为不可扩展对象,则该对象的属性不能够被代理隐藏

handler.ownKeys()open in new window

  • 描述:用于拦截 Reflect.ownKeys()
  • 参数
    • target:目标对象
  • 返回值:必须返回一个可枚举对象
  • 拦截操作
    • Object.getOwnPropertyNames()
    • Object.getOwnPropertySymbols()
    • Object.keys()
    • Reflect.ownKeys()
  • 注意:如果违背了以下的约束,proxy 会抛出 TypeError
    • ownKeys 的结果必须是一个数组
    • 数组的元素类型要么是一个 String ,要么是一个 Symbol
    • 结果列表必须包含目标对象的所有不可配置(non-configurable )、自有(own)属性的key
    • 如果目标对象不可扩展,那么结果列表必须包含目标对象的所有自有(own)属性的key,不能有其它值

handler.defineProperty()open in new window

  • 描述:用于拦截对对象的 Object.defineProperty()操作
  • 参数
    • target:目标对象
    • property:待检索其描述的属性名
    • descriptor:待定义或修改的属性的描述符
  • 返回值:必须以一个 Boolean 返回,表示定义该属性的操作成功与否
  • 拦截操作
    • Object.defineProperty()
    • Reflect.defineProperty()
  • 注意:如果违背了以下的约束,proxy 会抛出 TypeError
    • 如果目标对象不可扩展, 将不能添加属性
    • 不能添加或者修改一个属性为不可配置的,如果它不作为一个目标对象的不可配置的属性存在的话
    • 如果目标对象存在一个对应的可配置属性,这个属性可能不会是不可配置的
    • 如果一个属性在目标对象中存在对应的属性,那么 Object.defineProperty(target, prop, descriptor) 将不会抛出异常
    • 在严格模式下, false 作为 handler.defineProperty 方法的返回值的话将会抛出 TypeError 异常

handler.deleteProperty()open in new window

  • 描述:用于拦截对对象属性的 delete 操作
  • 参数
    • target:目标对象
    • property:待删除的属性名
  • 返回值:必须返回一个 Boolean 类型的值,表示了该属性是否被成功删除
  • 拦截操作
    • 删除属性 delete proxy[foo]delete proxy.foo
    • Reflect.deleteProperty()
  • 注意:如果违背了以下的约束,proxy 会抛出 TypeError
    • 如果目标对象的属性是不可配置的,那么该属性不能被删除

handler.apply()open in new window

  • 描述:用于拦截函数的调用
  • 参数
    • target:目标对象(函数)
    • thisArg:被调用时的上下文对象
    • argumentsList:被调用时的参数数组
  • 返回值:可以返回任何值
  • 拦截操作
    • proxy(...args)
    • Function.prototype.apply() Function.prototype.call()
    • Reflect.apply()
  • 注意:如果违背了以下的约束,proxy 会抛出 TypeError
    • target必须是可被调用的。也就是说,它必须是一个函数对象

handler.construct()open in new window

  • 描述:用于拦截 new 操作符
  • 参数
    • target:目标对象(函数)
    • argumentsList:constructor 的参数列表
    • newTarget:最初被调用的构造函数
  • 返回值:必须返回一个对象
  • 拦截操作
    • new proxy(...args)
    • Reflect.construct()
  • 注意:如果违背了以下的约束,proxy 会抛出 TypeError
    • 必须返回一个对象
上次编辑于:
贡献者: sunzhenyang