Get to know MDN better
此页面由社区从英文翻译而来。了解更多并加入 MDN Web Docs 社区。
Proxy 和 Reflect 对象允许你拦截并自定义基本语言操作(例如属性查找、赋值、枚举和函数调用等)。借助这两个对象,你可以在 JavaScript 进行元级别的编程。
Proxy 对象可以拦截某些操作并实现自定义行为。
例如获取一个对象上的属性:
Proxy 对象定义了一个 target(这里是一个空对象)和一个实现了 get 陷阱的 handler 对象。这里,代理的对象在获取未定义的属性时不会返回 undefined,而是返回 42。
更多例子参见 Proxy 页面。
在讨论代理的功能时会用到以下术语:
handler包含陷阱的占位符对象(下译作“处理器”)。
陷阱提供属性访问的方法(这类似于操作系统中陷阱的概念)。
target代理所虚拟化的对象(下译作“目标”)。它通常用作代理的存储后端。JavaScript 会验证与不可扩展性或不可配置属性相关的不变式。
不变式实现自定义操作时保持不变的语义称为不变式。如果你破坏了处理器的不变式,则会引发 TypeError 异常。
以下表格中总结了 Proxy 对象可用的陷阱。详细的解释和例子请看参考页。
| handler.getPrototypeOf() |
Object.getPrototypeOf() Reflect.getPrototypeOf() __proto__ Object.prototype.isPrototypeOf() instanceof |
|
| handler.setPrototypeOf() |
Object.setPrototypeOf() Reflect.setPrototypeOf() |
如果 target 不可扩展,参数 prototype 必须与 Object.getPrototypeOf(target) 的值相同。 |
| handler.isExtensible() |
Object.isExtensible() Reflect.isExtensible() |
Object.isExtensible(proxy) 必须返回和 Object.isExtensible(target) 一样的值。 |
| handler.preventExtensions() |
Object.preventExtensions() Reflect.preventExtensions() |
如果 Object.isExtensible(proxy) 值为 false,那么 Object.preventExtensions(proxy) 只可能返回 true。 |
| handler.getOwnPropertyDescriptor() |
Object.getOwnPropertyDescriptor() Reflect.getOwnPropertyDescriptor() |
|
| handler.defineProperty() |
Object.defineProperty() Reflect.defineProperty() |
|
| handler.has() |
属性查询
foo in proxy
继承属性查询
foo in Object.create(proxy) Reflect.has() |
|
| handler.get() |
属性访问
proxy[foo] proxy.bar 继承属性访问 Object.create(proxy)[foo] Reflect.get() |
|
| handler.set() |
属性赋值
proxy[foo] = bar proxy.foo = bar 继承属性赋值 Object.create(proxy)[foo] = bar Reflect.set() |
|
| handler.deleteProperty() |
属性删除
delete proxy[foo] delete proxy.foo Reflect.deleteProperty() |
如果存在一个对应于 target 的属性是不可配置的自有属性,那么该属性不能被删除。 |
| handler.ownKeys() |
Object.getOwnPropertyNames() Object.getOwnPropertySymbols() Object.keys() Reflect.ownKeys() |
|
| handler.apply() |
proxy(..args) Function.prototype.apply() Function.prototype.call() Reflect.apply() |
不存在关于 handler.apply 方法的不变式。 |
| handler.construct() |
new proxy(...args) Reflect.construct() |
返回值必须是一个 Object。 |
可以用 Proxy.revocable() 方法来创建可撤销的 Proxy 对象。这意味着可以通过 revoke 函数来撤销并关闭一个代理。
此后,对代理进行的任意的操作都会导致 TypeError。
Reflect 是一个内置对象,它为可拦截的 JavaScript 操作提供了方法。这些方法与代理处理器所提供的方法类似。
Reflect 并不是一个函数对象。
Reflect 将默认操作从处理器转发到 target。
以 Reflect.has() 为例,你可以将 in 运算符作为函数:
在不借助 Reflect 的情况下,我们通常使用 Function.prototype.apply() 方法调用一个具有给定 this 值和 arguments 数组(或类数组对象)的函数。
借助 Reflect.apply,这些操作将变得更加简洁:
使用 Object.defineProperty,如果成功则返回一个对象,否则抛出一个 TypeError,你可使用 try...catch 块来捕获定义属性时发生的任何错误。因为 Reflect.defineProperty 返回一个布尔值表示的成功状态,你可以在这里使用 if...else 块: