摘要:抛出当被检查的属性键存在与目标对象中,且该属性的配置是时,该监听方法不能返回。也可以将类作为目标监听对象,并监听其通过语句来生产新实例的行为,这同样可以使用再作为构造器的构造函数上。这里返回的结果会是所得到的实例创建可解除对象用法。
Proxy 让我们可以对任何对象的绝大部分行为进行监听和干涉,实现更多的自定义程序行为。
用法:new Proxy(target, handler)。
Proxy 通过设置行为监听方法来捕获程序对对应对象的行为。
const obj = {}; const proxy = new Proxy(obj, { // ... })
Proxy 的构造器接受两个参数,第一个参数为需要进行包装的目标对象,第二个参数则为用于监听目标对象行为的监听器,其中监听器可以接受一些参数以监听相对应的程序行为。
监听属性、参数及监听内容
属性值 | 监听器参数 | 监听内容 |
---|---|---|
has | (target, prop) | 监听 in 语句的使用 |
get | (target, prop, reciver) | 监听目标对象的属性读取 |
set | (target, prop, value, reciver) | 监听目标对象的属性赋值 |
deleteProperty | (target, prop) | 监听 delete 语句对目标对象的删除属性行为 |
ownKeys | (target) | 监听 Object.getOwnPropertyName() 的读取 |
apply | (target, thisArg, arguments) | 监听目标函数(作为目标对象)的调用行为 |
construct | (target, arguments, newTarget) | 监听目标构造函数(作为目标对象)利用 new 而生成实例的行为 |
getPrototypeOf | (target) | 监听 Objext.getPrototypeOf() 的读取 |
setPrototypeOf | (target, prototype) | 监听 Objext.setPrototypeOf() 的调用 |
isExtensible | (target) | 监听 Objext.isExtensible() 的读取 |
preventExtensions | (target) | 监听 Objext.preventExtensions() 的读取 |
getOwnPropertyDescriptor | (target, prop) | 监听 Objext.getOwnPropertyDescriptor() 的调用 |
defineProperty | (target, property, descriptor) | 监听 Object.defineProperty() 的调用 |
可以通过为 Proxy 的 handler 定义 has 监听方法,来监听程序通过 in 语句来检查一个字符串或数字是否为该 Proxy 的目标对象中某个属性的属性键的过程。
const p = new Proxy({}, { has(target, prop){ console.log(`Checking "${prop}" is in the target or not`); return true; } }) console.log("foo" in p); // Checking "foo" is in the target or not // true
该监听方法有两个需要注意的地方,如果遇到这两种情况,便会抛出 TypeError 错误。
1.当目标对象被其他程序通过 Object.preventExtensions() 禁用了属性拓展 (该对象无法再增加新的属性,只能对当前已有的属性进行操作,包括读取、操作和删除,但是一旦删除就无法再定义) 功能,且被检查的属性键确实存在与目标对象中,该监听方法便不能返回 false。
const obj = {foo: 1}; Object.preventExtensions(obj); const p = new Proxy(obj, { has(target, prop){ console.log(`Checking "${prop}" is in the target or not`); return false; } }) console.log("foo" in p); //抛出Uncaught TypeError:
2.当被检查的属性键存在与目标对象中,且该属性的 configurable 配置是 false 时,该监听方法不能返回 false。
const obj = {}; Object.defineProperty(obj, "foo", { configurable: false, value: 10 }) const p = new Proxy(obj, { has(target, prop){ console.log(`Checking "${prop}" is in the target or not`); return false; } }) console.log("foo" in p); //抛出Uncaught TypeError:get
Getter只能对已知的属性键进行监听,而无法对所有属性读取行为进行拦截,而 Proxy 可以通过设定 get 监听方法,拦截和干涉目标对象的所有属性读取行为。
const obj = {foo: 1}; const p = new Proxy(obj, { get(target, prop){ console.log(`Program is trying to fetch the property "${prop}".`); return target[prop]; } }) alert(p.foo); // Program is trying to fetch the property "foo". alert(p.something); // Program is trying to fetch the property "something".
这个监听方法也存在需要注意的地方——当目标对象被读取属性的 configurable 和 writable 属性都为 false 时,监听方法最后返回的值必须与目标对象的原属性值一致。
const obj = {}; Object.defineProperty(obj, "foo", { configurable: false, value: 10, writable: false }) const p = new Proxy(obj, { get(target, prop){ return 20; } }) console.log(p.foo);set
handler.set 用于监听目标对象的所有属性赋值行为。注意,如果目标对象自身的某个属性是不可写也不可配置的,那么 set 不得改变这个属性的值,只能返回同样的值,否则报错。
const obj = {}; const p = new Proxy(obj, { set(target, prop, value){ console.log(`Setting value "${value}" on the key "${prop}" in the target object`); target[prop] = value; return true; } }) p.foo = 1; // Setting value "1" on the key "foo" in the target objectapply
handler.apply , Proxy 也为作为目标对象的函数提供了监听其调用行为的属性。
const sum = function(...args) { return args .map(Number) .filter(Boolean) .reduce((a, b) => a + b); } const p = new Proxy(sum, { apply(target, thisArg, args) { console.log(`Function is being called with arguments [${args.join()}] and context ${thisArg}`); return target.call(thisArg, ...args); } }) console.log(p(1, 2, 3)); // Function is being called with arguments [1,2,3] and context undefined // 6construct
handler.construct, Proxy 也可以将类作为目标监听对象,并监听其通过 new 语句来生产新实例的行为,这同样可以使用再作为构造器的构造函数上。
class Foo{}; const p = new Proxy(Foo, { construct(target, args, newTarget){ return {arguments: args} // 这里返回的结果会是 new 所得到的实例 } }); const obj = new p(1, 2, 3); console.log(obj.arguments); // [1, 2, 3]创建可解除 Proxy 对象
用法:Proxy.revocable(target, handler) : (proxy, revoke)。
const obj = {foo: 10}; const revocable = Proxy.revocable(obj, { get(target, prop){ return 20; } }) const proxy = revocable.proxy; console.log(proxy.foo); // 20 revocable.revoke(); console.log(proxy.foo); // TypeError: Cannot perform "get" on a proxy that has been revoked
Proxy.revocable(target, handler) 会返回一个带有两个属性的对象,其中一个 proxy 便是该函数所生成的可解除 Proxy 对象,而另一个 revoke 则是将刚才的 Proxy 对象解除的解除方法。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/99895.html
摘要:关于如何快速调教的几点总结关于的好与坏,我觉得没有必要去介绍了,在这里主要分享一下我在实际的项目部署中是如何快速的调教的。 关于如何快速调教Nginx的几点总结 关于Nginx的好与坏,我觉得没有必要去介绍了,在这里主要分享一下我在实际的项目部署中是如何快速的调教Nginx的。其中分享的源码大家可以作为模板代码,根据自身项目的实际情况,酌情使用。 这里简单的说一说我为什么要写这篇文章,...
摘要:本文是重温基础系列文章的第十四篇。元,是指程序本身。有理解不到位,还请指点,具体详细的介绍,可以查看维基百科元编程。拦截,返回一个布尔值。 本文是 重温基础 系列文章的第十四篇。 这是第一个基础系列的最后一篇,后面会开始复习一些中级的知识了,欢迎持续关注呀! 接下来会统一整理到我的【Cute-JavaScript】的JavaScript基础系列中。 今日感受:独乐乐不如众乐乐...
阅读 1418·2021-09-03 10:29
阅读 3414·2019-08-29 16:24
阅读 1967·2019-08-29 11:03
阅读 1388·2019-08-26 13:52
阅读 2899·2019-08-26 11:36
阅读 2772·2019-08-23 17:19
阅读 544·2019-08-23 17:14
阅读 764·2019-08-23 13:59