Proxy与Reflect

Proxy

构造函数

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

语法:new Proxy(target, handler)

参数:

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

方法

Proxy.revocable()

Proxy.revocable() 方法可以用来创建一个可撤销的代理对象。

语法:Proxy.revocable(target, handler)

  • target:将用 Proxy 封装的目标对象。可以是任何类型的对象,包括原生数组,函数,甚至可以是另外一个代理对象。
  • handler:一个对象,其属性是一批可选的函数,这些函数定义了对应的操作被执行时代理的行为。

handler 对象的方法

handler 对象是一个容纳一批特定属性的占位符对象。它包含有 Proxy 的各个捕获器(trap)。

所有的捕捉器是可选的。如果没有定义某个捕捉器,那么就会保留源对象的默认行为。

handler.get()

handler.get() 方法用于拦截对象的读取属性操作。

语法:

new Proxy(target, {
  get(target, property, receiver) {},
});

参数:

  • target:目标对象
  • property:被获取的属性名
  • receiver:Proxy 或者继承 Proxy 的对象

返回:返回任何值

该方法会拦截目标对象的以下操作:

  • 访问属性:proxy[foo] 和 proxy.bar
  • 访问原型链上的属性:Object.create(proxy)[foo]
  • Reflect.get()

如果违背了以下的约束,proxy 会抛出 TypeError:

  • 如果要访问的目标属性是不可写以及不可配置的,则返回的值必须与该目标属性的值相同
  • 如果要访问的目标属性没有配置访问方法,即 get 方法是 undefined 的,则返回值必须为 undefined

handler.set()

handler.set() 方法是设置属性值操作的捕获器。

语法:

new Proxy(target, {
  set(target, property, value, receiver) {}
});

参数:

  • target:目标对象
  • property:被获取的属性名
  • value:新属性值
  • receiver:Proxy 或者继承 Proxy 的对象

返回:返回一个布尔值

  • 返回 true 代表属性设置成功
  • 在严格模式下,如果 set() 方法返回 false,那么会抛出一个 TypeError 异常

该方法会拦截目标对象的以下操作:

  • 指定属性值:proxy[foo] = barproxy.foo = bar
  • 指定继承者的属性值:Object.create(proxy)[foo] = bar
  • Reflect.set()

如果违背以下的约束条件,proxy 会抛出一个 TypeError 异常:

  • 若目标属性是一个不可写及不可配置的数据属性,则不能改变它的值
  • 如果目标属性没有配置存储方法,即 [[Set]] 属性的是 undefined,则不能设置它的值
  • 在严格模式下,如果 set() 方法返回 false,那么也会抛出一个 TypeError 异常

handler.has()

handler.has() 方法是针对 in 操作符的代理方法。

语法:

new Proxy(target, {
  has(target, prop) {},
});

参数:

  • target:目标对象
  • prop:需要检查是否存在的属性

返回:返回一个 boolean 属性的值

这个钩子可以拦截下面这些操作:

  • 属性查询:foo in proxy
  • 继承属性查询:foo in Object.create(proxy)
  • with 检查: with(proxy) { (foo); }
  • Reflect.has()

如果违反了下面这些规则,proxy 将会抛出 TypeError:

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

handler.apply()

handler.apply() 方法用于拦截函数的调用。

语法:

new Proxy(target, {
  apply(target, thisArg, argumentsList) {},
});

参数:

  • target:目标对象(函数)
  • thisArg:被调用时的上下文对象
  • argumentsList:被调用时的参数数组

返回:返回任何值

该方法会拦截目标对象的以下操作:

  • proxy(...args)
  • Function.prototype.apply()Function.prototype.call()
  • Reflect.apply()

handler.construct()

handler.construct() 方法用于拦截 new 操作符。为了使 new 操作符在生成的 Proxy 对象上生效,用于初始化代理的目标对象自身必须具有 [[Construct]] 内部方法(即 new target 必须是有效的)。

语法:

new Proxy(target, {
  construct(target, argumentsList, newTarget) {},
});

参数:

  • target:目标对象
  • argumentsList:constructor 的参数列表
  • newTarget:最初被调用的构造函数,就上面的例子而言是 p

返回:返回一个对象

该拦截器可以拦截以下操作:

  • new proxy(...args)
  • Reflect.construct()

如果违反以下约定,代理将会抛出错误 TypeError:

  • 必须返回一个对象

handler.deleteProperty()

handler.deleteProperty() 方法用于拦截对对象属性的 delete 操作。

语法:

new Proxy(target, {
  deleteProperty(target, property) {},
});

参数:

  • target:目标对象
  • property:被获取的属性名

返回:返回一个 Boolean 类型的值,表示了该属性是否被成功删除

该方法会拦截以下操作:

  • 删除属性:delete proxy[foo]delete proxy.foo
  • Reflect.deleteProperty()

如果违背了以下不变量,proxy 将会抛出一个 TypeError:

  • 如果目标对象的属性是不可配置的,那么该属性不能被删除。

handler.ownKeys()

handler.ownKeys() 方法用于拦截 Reflect.ownKeys()

语法:

new Proxy(target, {
  ownKeys(target) {},
});

参数:

  • target:目标对象

返回:返回一个可枚举对象

该拦截器可以拦截以下操作::

  • Object.getOwnPropertyNames()
  • Object.getOwnPropertySymbols()
  • Object.keys()
  • Reflect.ownKeys()

如果违反了下面的约束,proxy 将抛出错误 TypeError:

  • ownKeys 的结果必须是一个数组
  • 数组的元素类型要么是一个 String ,要么是一个 Symbol
  • 结果列表必须包含目标对象的所有不可配置(non-configurable)、自有(own)属性的 key
  • 如果目标对象不可扩展,那么结果列表必须包含目标对象的所有自有(own)属性的 key,不能有其他值

handler.getPrototypeOf()

handler.getPrototypeOf() 是一个代理(Proxy)方法,当读取代理对象的原型时,该方法就会被调用。

语法:

new Proxy(target, {
  getPrototypeOf(target) {}
})

参数:

  • target:被代理的目标对象。

返回:返回一个对象或者 null

这个方法可以拦截以下操作:

  • Object.getPrototypeOf()
  • Reflect.getPrototypeOf()
  • Object.prototype.__proto__
  • Object.prototype.isPrototypeOf()
  • instanceof

如果遇到了下面情况,JS 引擎会抛出 TypeError 异常:

  • getPrototypeOf() 方法返回的不是对象也不是 null
  • 目标对象是不可扩展的,且 getPrototypeOf() 方法返回的原型不是目标对象本身的原型

handler.setPrototypeOf()

handler.setPrototypeOf() 方法主要用来拦截 Object.setPrototypeOf().

语法:

new Proxy(target, {
  setPrototypeOf(target, prototype) {}
})

参数:

  • target:被拦截目标对象
  • prototype:对象新原型或为 null

返回:如果成功修改了[[Prototype]],返回 true,否则返回 false

这个方法可以拦截以下操作:

  • Object.setPrototypeOf()
  • Reflect.setPrototypeOf()

如果遇到了下面情况,JS 引擎会抛出 TypeError 异常:

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

handler.isExtensible()

handler.isExtensible() 方法用于拦截对对象的 Object.isExtensible()

语法:

new Proxy(target, {
  isExtensible(target) {}
})

参数:

  • target:目标对象

返回:返回一个 Boolean 值或可转换成 Boolean 的值

这个方法可以拦截以下操作:

  • Object.isExtensible()
  • Reflect.isExtensible()

如果遇到了下面情况,JS 引擎会抛出 TypeError 异常:

  • Object.isExtensible(proxy) 必须同 Object.isExtensible(target) 返回相同值

handler.preventExtensions()

handler.preventExtensions() 方法用于设置对 Object.preventExtensions() 的拦截。

语法:

new Proxy(target, {
  preventExtensions(target) {}
})

参数:

  • target:所要拦截的目标对象

返回:返回一个布尔值

这个方法可以拦截以下操作:

  • Object.preventExtensions()
  • Reflect.preventExtensions()

如果遇到了下面情况,JS 引擎会抛出 TypeError 异常:

  • 如果目标对象是可扩展的,那么只能返回 false

handler.getOwnPropertyDescriptor()

handler.getOwnPropertyDescriptor() 方法是 Object.getOwnPropertyDescriptor() 的钩子。

语法:

new Proxy(target, {
  getOwnPropertyDescriptor(target, prop) {}
})

参数:

  • target:所要拦截的目标对象
  • prop:返回属性名称的描述

返回:返回一个 object 或 undefined

这个方法可以拦截以下操作:

  • Object.getOwnPropertyDescriptor()
  • Reflect.getOwnPropertyDescriptor()

如果下列不变量被违反,代理将抛出一个 TypeError

  • getOwnPropertyDescriptor 必须返回一个 object 或 undefined
  • 如果属性作为目标对象的不可配置的属性存在,则该属性无法报告为不存在。
  • 如果属性作为目标对象的属性存在,并且目标对象不可扩展,则该属性无法报告为不存在。
  • 如果属性不存在作为目标对象的属性,并且目标对象不可扩展,则不能将其报告为存在。
  • 属性不能被报告为不可配置,如果它不作为目标对象的自身属性存在,或者作为目标对象的可配置的属性存在。
  • Object.getOwnPropertyDescriptor(target)的结果可以使用 Object.defineProperty 应用于目标对象,也不会抛出异常。

handler.defineProperty()

handler.defineProperty() 用于拦截对象的 Object.defineProperty() 操作。

语法:

new Proxy(target, {
  defineProperty(target, property, descriptor) {}
})

参数:

  • target:目标对象
  • property:待检索其描述的属性名
  • descriptor:待定义或修改的属性的描述符

返回:返回 Boolean,表示定义该属性的操作成功与否

该方法会拦截目标对象的以下操作:

  • Object.defineProperty()
  • Reflect.defineProperty()
  • proxy.property='value'

如果违背了以下的不变量,proxy 会抛出 TypeError:

  • 如果目标对象不可扩展,将不能添加属性
  • 不能添加或者修改一个属性为不可配置的,如果它不作为一个目标对象的不可配置的属性存在的话
  • 如果目标对象存在一个对应的可配置属性,这个属性可能不会是不可配置的
  • 如果一个属性在目标对象中存在对应的属性,那么 Object.defineProperty(target, prop, descriptor) 将不会抛出异常
  • 在严格模式下,false 作为 handler.defineProperty 方法的返回值的话将会抛出 TypeError 异常

Reflect

Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与 proxy.handler 的方法相同。

Reflect 不是一个函数对象,因此它是不可构造的。

你可能感兴趣的:(JS,java,javascript,前端)