摘要:是陷阱函數(shù)對(duì)應(yīng)的反射方法,同時(shí)也是操作的默認(rèn)行為。對(duì)象外形指的是對(duì)象已有的屬性與方法的集合,由于該屬性驗(yàn)證只須在讀取屬性時(shí)被觸發(fā),因此只要使用陷阱函數(shù)。無論該屬性是對(duì)象自身的屬性還是其原型的屬性。
主要知識(shí)點(diǎn):代理和反射的定義、常用的陷阱函數(shù)、可被撤銷的代理、將代理對(duì)象作為原型使用、將代理作為類的原型
《深入理解ES6》筆記 目錄
代理與反射代理是什么?
通過調(diào)用 new Proxy() ,你可以創(chuàng)建一個(gè)代理用來替代另一個(gè)對(duì)象(被稱之為目目標(biāo)對(duì)象) ,這個(gè)代理對(duì)目標(biāo)對(duì)象進(jìn)行了虛擬,因此該代理與該目標(biāo)對(duì)象表面上可以被當(dāng)作同一個(gè)對(duì)象來對(duì)待。
代理允許你攔截目標(biāo)對(duì)象上的底層操作,而這本來是JS引擎的內(nèi)部能力,攔截行為適用了一個(gè)能響應(yīng)特定操作的函數(shù)(被稱之為陷阱);
反射是什么?
被Reflect對(duì)象所代表的反射接口,是給底層操作提供默認(rèn)行為的方法的集合,這些操作是能夠被代理重寫的。每個(gè)代理陷阱都有一個(gè)對(duì)應(yīng)的反射方法,每個(gè)方法都與對(duì)應(yīng)的陷阱函數(shù)同名,并且接收的參數(shù)也與之一致。
創(chuàng)建一個(gè)簡(jiǎn)單的代理使用Proxy構(gòu)建可以創(chuàng)建一個(gè)簡(jiǎn)單的代理對(duì)象,需要傳遞兩個(gè)參數(shù):目標(biāo)對(duì)象以及一個(gè)處理器,后者是定義一個(gè)或多個(gè)陷阱函數(shù)的對(duì)象。如果不定義陷阱函數(shù),則依然使用目標(biāo)對(duì)象的默認(rèn)行為:
let target = {}; let proxy = new Proxy(target, {}); proxy.name = "proxy"; console.log(proxy.name); // "proxy" console.log(target.name); // "proxy" target.name = "target"; console.log(proxy.name); // "target" console.log(target.name); // "target"使用 set 陷阱函數(shù)驗(yàn)證屬性值
假設(shè)你想要?jiǎng)?chuàng)建一個(gè)對(duì)象,并要求其屬性值只能是數(shù)值,這就意味著該對(duì)象的每個(gè)新增屬性都要被驗(yàn)證,并且在屬性值不為數(shù)值類型時(shí)應(yīng)當(dāng)拋出錯(cuò)誤。為此你需要定義 set 陷阱函數(shù)來重寫設(shè)置屬性值時(shí)的默認(rèn)行為,該陷阱函數(shù)能接受四個(gè)參數(shù):
trapTarget :將接收屬性的對(duì)象(即代理的目標(biāo)對(duì)象);
key :需要寫入的屬性的鍵(字符串類型或符號(hào)類型);
value :將被寫入屬性的值;
receiver :操作發(fā)生的對(duì)象(通常是代理對(duì)象)。
Reflect.set() 是 set 陷阱函數(shù)對(duì)應(yīng)的反射方法,同時(shí)也是 set 操作的默認(rèn)行為。
Reflect.set() 方法與 set 陷阱函數(shù)一樣,能接受這四個(gè)參數(shù),讓該方法能在陷阱函數(shù)內(nèi)部被方便使用:
let target = { name: "target" }; let proxy = new Proxy(target, { set(trapTarget, key, value, receiver) { // 忽略已有屬性,避免影響它們 if (!trapTarget.hasOwnProperty(key)) { if (isNaN(value)) { throw new TypeError("Property must be a number."); } } // 添加屬性 return Reflect.set(trapTarget, key, value, receiver); } }); // 添加一個(gè)新屬性 proxy.count = 1; console.log(proxy.count); // 1 console.log(target.count); // 1 // 你可以為 name 賦一個(gè)非數(shù)值類型的值,因?yàn)樵搶傩砸呀?jīng)存在 proxy.name = "proxy"; console.log(proxy.name); // "proxy" console.log(target.name); // "proxy" // 拋出錯(cuò)誤 proxy.anotherName = "proxy";使用 get 陷阱函數(shù)進(jìn)行對(duì)象外形驗(yàn)證
JS 語言有趣但有時(shí)卻令人困惑的特性之一,就是讀取對(duì)象不存在的屬性時(shí)并不會(huì)拋出錯(cuò)誤,而會(huì)把 undefined 當(dāng)作該屬性的值,例如:
let target = {}; console.log(target.name); // undefined
在多數(shù)語言中,試圖讀取 target.name 屬性都會(huì)拋出錯(cuò)誤,因?yàn)樵搶傩圆⒉淮嬖冢坏?JS 語言卻會(huì)使用 undefined 。
對(duì)象外形( Object Shape )指的是對(duì)象已有的屬性與方法的集合,由于該屬性驗(yàn)證只須在讀取屬性時(shí)被觸發(fā),因此只要使用 get 陷阱函數(shù)。該陷阱函數(shù)會(huì)在讀取屬性時(shí)被調(diào)用,即使該屬性在對(duì)象中并不存在,它能接受三個(gè)參數(shù):
trapTarget :將會(huì)被讀取屬性的對(duì)象(即代理的目標(biāo)對(duì)象);
key :需要讀取的屬性的鍵(字符串類型或符號(hào)類型);
receiver :操作發(fā)生的對(duì)象(通常是代理對(duì)象)。
相應(yīng)的Reflect.get()方法同樣擁有這三個(gè)參數(shù)。進(jìn)行對(duì)象外形驗(yàn)證的示例代碼:
//import {color,sum,magicNumber} from "./export.js" import * as example from "./export.js" console.log(example.color) console.log(example.magicNumber) console.log(example. sum(76, 2)) let proxy = new Proxy({}, { get(trapTarget, key, receiver) { if (!(key in receiver)) { throw new TypeError("Property " + key + " doesn"t exist."); } return Reflect.get(trapTarget, key, receiver); } }); // 添加屬性的功能正常 proxy.name = "proxy"; console.log(proxy.name); // "proxy" // 讀取不存在屬性會(huì)拋出錯(cuò)誤 console.log(proxy.nme); // 拋出錯(cuò)誤使用 has 陷阱函數(shù)隱藏屬性
in運(yùn)算符用于判斷指定對(duì)象中是否存在某個(gè)屬性,如果對(duì)象的屬性名與指定的字符串或符號(hào)值相匹配,那么in運(yùn)算符就會(huì)返回true。無論該屬性是對(duì)象自身的屬性還是其原型的屬性。
has陷阱函數(shù)會(huì)在使用in運(yùn)算符的情況下被調(diào)用,控制in運(yùn)算符返回不同的結(jié)果,has陷阱函數(shù)會(huì)傳入兩個(gè)參數(shù):
trapTarget:代理的目標(biāo)對(duì)象;
key:屬性鍵;
Reflect.has()方法接收相同的參數(shù),并向in運(yùn)算符返回默認(rèn)的響應(yīng)結(jié)果,用于返回默認(rèn)響應(yīng)結(jié)果。
let target = { name: "target", value: 42 }; let proxy = new Proxy(target, { has(trapTarget, key) { if (key === "value") { return false; } else { return Reflect.has(trapTarget, key); } } }); console.log("value" in proxy); // false console.log("name" in proxy); // true console.log("toString" in proxy); // true
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/97024.html
摘要:方法與代理處理程序的方法相同。使用給目標(biāo)函數(shù)傳入指定的參數(shù)。當(dāng)然,不用反射也可以讀取的值。的例子我們可以理解成是攔截了方法,然后傳入?yún)?shù),將返回值賦值給,這樣我們就能在需要讀取這個(gè)返回值的時(shí)候調(diào)用。這種代理模式和的代理有異曲同工之妙。 反射 Reflect 當(dāng)你見到一個(gè)新的API,不明白的時(shí)候,就在瀏覽器打印出來看看它的樣子。 showImg(https://segmentfault....
摘要:方法與代理處理程序的方法相同。使用給目標(biāo)函數(shù)傳入指定的參數(shù)。當(dāng)然,不用反射也可以讀取的值。的例子我們可以理解成是攔截了方法,然后傳入?yún)?shù),將返回值賦值給,這樣我們就能在需要讀取這個(gè)返回值的時(shí)候調(diào)用。這種代理模式和的代理有異曲同工之妙。 反射 Reflect 當(dāng)你見到一個(gè)新的API,不明白的時(shí)候,就在瀏覽器打印出來看看它的樣子。 showImg(https://segmentfault....
摘要:最近買了深入理解的書籍來看,為什么學(xué)習(xí)這么久還要買這本書呢主要是看到核心團(tuán)隊(duì)成員及的創(chuàng)造者為本書做了序,作為一個(gè)粉絲,還是挺看好這本書能給我?guī)硪粋€(gè)新的升華,而且本書的作者也非常厲害。 使用ES6開發(fā)已經(jīng)有1年多了,以前看的是阮一峰老師的ES6教程,也看過MDN文檔的ES6語法介紹。 最近買了《深入理解ES6》的書籍來看,為什么學(xué)習(xí)ES6這么久還要買這本書呢?主要是看到Daniel A...
閱讀 842·2023-04-25 22:13
閱讀 2351·2019-08-30 15:56
閱讀 2234·2019-08-30 11:21
閱讀 661·2019-08-30 11:13
閱讀 2029·2019-08-26 14:06
閱讀 1966·2019-08-26 12:11
閱讀 2297·2019-08-23 16:55
閱讀 546·2019-08-23 15:30