摘要:拋出當(dāng)被檢查的屬性鍵存在與目標(biāo)對(duì)象中,且該屬性的配置是時(shí),該監(jiān)聽方法不能返回。也可以將類作為目標(biāo)監(jiān)聽對(duì)象,并監(jiān)聽其通過(guò)語(yǔ)句來(lái)生產(chǎn)新實(shí)例的行為,這同樣可以使用再作為構(gòu)造器的構(gòu)造函數(shù)上。這里返回的結(jié)果會(huì)是所得到的實(shí)例創(chuàng)建可解除對(duì)象用法。
Proxy 讓我們可以對(duì)任何對(duì)象的絕大部分行為進(jìn)行監(jiān)聽和干涉,實(shí)現(xiàn)更多的自定義程序行為。
用法:new Proxy(target, handler)。
?? Proxy 通過(guò)設(shè)置行為監(jiān)聽方法來(lái)捕獲程序?qū)?duì)應(yīng)對(duì)象的行為。
const obj = {}; const proxy = new Proxy(obj, { // ... })
Proxy 的構(gòu)造器接受兩個(gè)參數(shù),第一個(gè)參數(shù)為需要進(jìn)行包裝的目標(biāo)對(duì)象,第二個(gè)參數(shù)則為用于監(jiān)聽目標(biāo)對(duì)象行為的監(jiān)聽器,其中監(jiān)聽器可以接受一些參數(shù)以監(jiān)聽相對(duì)應(yīng)的程序行為。
監(jiān)聽屬性、參數(shù)及監(jiān)聽內(nèi)容
屬性值 | 監(jiān)聽器參數(shù) | 監(jiān)聽內(nèi)容 |
---|---|---|
has | (target, prop) | 監(jiān)聽 in 語(yǔ)句的使用 |
get | (target, prop, reciver) | 監(jiān)聽目標(biāo)對(duì)象的屬性讀取 |
set | (target, prop, value, reciver) | 監(jiān)聽目標(biāo)對(duì)象的屬性賦值 |
deleteProperty | (target, prop) | 監(jiān)聽 delete 語(yǔ)句對(duì)目標(biāo)對(duì)象的刪除屬性行為 |
ownKeys | (target) | 監(jiān)聽 Object.getOwnPropertyName() 的讀取 |
apply | (target, thisArg, arguments) | 監(jiān)聽目標(biāo)函數(shù)(作為目標(biāo)對(duì)象)的調(diào)用行為 |
construct | (target, arguments, newTarget) | 監(jiān)聽目標(biāo)構(gòu)造函數(shù)(作為目標(biāo)對(duì)象)利用 new 而生成實(shí)例的行為 |
getPrototypeOf | (target) | 監(jiān)聽 Objext.getPrototypeOf() 的讀取 |
setPrototypeOf | (target, prototype) | 監(jiān)聽 Objext.setPrototypeOf() 的調(diào)用 |
isExtensible | (target) | 監(jiān)聽 Objext.isExtensible() 的讀取 |
preventExtensions | (target) | 監(jiān)聽 Objext.preventExtensions() 的讀取 |
getOwnPropertyDescriptor | (target, prop) | 監(jiān)聽 Objext.getOwnPropertyDescriptor() 的調(diào)用 |
defineProperty | (target, property, descriptor) | 監(jiān)聽 Object.defineProperty() 的調(diào)用 |
可以通過(guò)為 Proxy 的 handler 定義 has 監(jiān)聽方法,來(lái)監(jiān)聽程序通過(guò) in 語(yǔ)句來(lái)檢查一個(gè)字符串或數(shù)字是否為該 Proxy 的目標(biāo)對(duì)象中某個(gè)屬性的屬性鍵的過(guò)程。
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
該監(jiān)聽方法有兩個(gè)需要注意的地方,如果遇到這兩種情況,便會(huì)拋出 TypeError 錯(cuò)誤。
1.當(dāng)目標(biāo)對(duì)象被其他程序通過(guò) Object.preventExtensions() 禁用了屬性拓展 (該對(duì)象無(wú)法再增加新的屬性,只能對(duì)當(dāng)前已有的屬性進(jìn)行操作,包括讀取、操作和刪除,但是一旦刪除就無(wú)法再定義) 功能,且被檢查的屬性鍵確實(shí)存在與目標(biāo)對(duì)象中,該監(jiān)聽方法便不能返回 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.當(dāng)被檢查的屬性鍵存在與目標(biāo)對(duì)象中,且該屬性的 configurable 配置是 false 時(shí),該監(jiān)聽方法不能返回 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只能對(duì)已知的屬性鍵進(jìn)行監(jiān)聽,而無(wú)法對(duì)所有屬性讀取行為進(jìn)行攔截,而 Proxy 可以通過(guò)設(shè)定 get 監(jiān)聽方法,攔截和干涉目標(biāo)對(duì)象的所有屬性讀取行為。
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".
??這個(gè)監(jiān)聽方法也存在需要注意的地方——當(dāng)目標(biāo)對(duì)象被讀取屬性的 configurable 和 writable 屬性都為 false 時(shí),監(jiān)聽方法最后返回的值必須與目標(biāo)對(duì)象的原屬性值一致。
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 用于監(jiān)聽目標(biāo)對(duì)象的所有屬性賦值行為。注意,如果目標(biāo)對(duì)象自身的某個(gè)屬性是不可寫也不可配置的,那么 set 不得改變這個(gè)屬性的值,只能返回同樣的值,否則報(bào)錯(cuò)。
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 也為作為目標(biāo)對(duì)象的函數(shù)提供了監(jiān)聽其調(diào)用行為的屬性。
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 也可以將類作為目標(biāo)監(jiān)聽對(duì)象,并監(jiān)聽其通過(guò) new 語(yǔ)句來(lái)生產(chǎn)新實(shí)例的行為,這同樣可以使用再作為構(gòu)造器的構(gòu)造函數(shù)上。
class Foo{}; const p = new Proxy(Foo, { construct(target, args, newTarget){ return {arguments: args} // 這里返回的結(jié)果會(huì)是 new 所得到的實(shí)例 } }); const obj = new p(1, 2, 3); console.log(obj.arguments); // [1, 2, 3]創(chuàng)建可解除 Proxy 對(duì)象
用法: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) 會(huì)返回一個(gè)帶有兩個(gè)屬性的對(duì)象,其中一個(gè) proxy 便是該函數(shù)所生成的可解除 Proxy 對(duì)象,而另一個(gè) revoke 則是將剛才的 Proxy 對(duì)象解除的解除方法。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/99895.html
摘要:關(guān)于如何快速調(diào)教的幾點(diǎn)總結(jié)關(guān)于的好與壞,我覺得沒有必要去介紹了,在這里主要分享一下我在實(shí)際的項(xiàng)目部署中是如何快速的調(diào)教的。 關(guān)于如何快速調(diào)教N(yùn)ginx的幾點(diǎn)總結(jié) 關(guān)于Nginx的好與壞,我覺得沒有必要去介紹了,在這里主要分享一下我在實(shí)際的項(xiàng)目部署中是如何快速的調(diào)教N(yùn)ginx的。其中分享的源碼大家可以作為模板代碼,根據(jù)自身項(xiàng)目的實(shí)際情況,酌情使用。 這里簡(jiǎn)單的說(shuō)一說(shuō)我為什么要寫這篇文章,...
摘要:本文是重溫基礎(chǔ)系列文章的第十四篇。元,是指程序本身。有理解不到位,還請(qǐng)指點(diǎn),具體詳細(xì)的介紹,可以查看維基百科元編程。攔截,返回一個(gè)布爾值。 本文是 重溫基礎(chǔ) 系列文章的第十四篇。 這是第一個(gè)基礎(chǔ)系列的最后一篇,后面會(huì)開始復(fù)習(xí)一些中級(jí)的知識(shí)了,歡迎持續(xù)關(guān)注呀! 接下來(lái)會(huì)統(tǒng)一整理到我的【Cute-JavaScript】的JavaScript基礎(chǔ)系列中。 今日感受:獨(dú)樂樂不如眾樂樂...
閱讀 1448·2021-09-03 10:29
閱讀 3470·2019-08-29 16:24
閱讀 2041·2019-08-29 11:03
閱讀 1425·2019-08-26 13:52
閱讀 2937·2019-08-26 11:36
閱讀 2800·2019-08-23 17:19
閱讀 572·2019-08-23 17:14
閱讀 822·2019-08-23 13:59