摘要:是陷阱函數對應的反射方法,同時也是操作的默認行為。對象外形指的是對象已有的屬性與方法的集合,由于該屬性驗證只須在讀取屬性時被觸發,因此只要使用陷阱函數。無論該屬性是對象自身的屬性還是其原型的屬性。
主要知識點:代理和反射的定義、常用的陷阱函數、可被撤銷的代理、將代理對象作為原型使用、將代理作為類的原型
《深入理解ES6》筆記 目錄
代理與反射代理是什么?
通過調用 new Proxy() ,你可以創建一個代理用來替代另一個對象(被稱之為目目標對象) ,這個代理對目標對象進行了虛擬,因此該代理與該目標對象表面上可以被當作同一個對象來對待。
代理允許你攔截目標對象上的底層操作,而這本來是JS引擎的內部能力,攔截行為適用了一個能響應特定操作的函數(被稱之為陷阱);
反射是什么?
被Reflect對象所代表的反射接口,是給底層操作提供默認行為的方法的集合,這些操作是能夠被代理重寫的。每個代理陷阱都有一個對應的反射方法,每個方法都與對應的陷阱函數同名,并且接收的參數也與之一致。
創建一個簡單的代理使用Proxy構建可以創建一個簡單的代理對象,需要傳遞兩個參數:目標對象以及一個處理器,后者是定義一個或多個陷阱函數的對象。如果不定義陷阱函數,則依然使用目標對象的默認行為:
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 陷阱函數驗證屬性值
假設你想要創建一個對象,并要求其屬性值只能是數值,這就意味著該對象的每個新增屬性都要被驗證,并且在屬性值不為數值類型時應當拋出錯誤。為此你需要定義 set 陷阱函數來重寫設置屬性值時的默認行為,該陷阱函數能接受四個參數:
trapTarget :將接收屬性的對象(即代理的目標對象);
key :需要寫入的屬性的鍵(字符串類型或符號類型);
value :將被寫入屬性的值;
receiver :操作發生的對象(通常是代理對象)。
Reflect.set() 是 set 陷阱函數對應的反射方法,同時也是 set 操作的默認行為。
Reflect.set() 方法與 set 陷阱函數一樣,能接受這四個參數,讓該方法能在陷阱函數內部被方便使用:
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); } }); // 添加一個新屬性 proxy.count = 1; console.log(proxy.count); // 1 console.log(target.count); // 1 // 你可以為 name 賦一個非數值類型的值,因為該屬性已經存在 proxy.name = "proxy"; console.log(proxy.name); // "proxy" console.log(target.name); // "proxy" // 拋出錯誤 proxy.anotherName = "proxy";使用 get 陷阱函數進行對象外形驗證
JS 語言有趣但有時卻令人困惑的特性之一,就是讀取對象不存在的屬性時并不會拋出錯誤,而會把 undefined 當作該屬性的值,例如:
let target = {}; console.log(target.name); // undefined
在多數語言中,試圖讀取 target.name 屬性都會拋出錯誤,因為該屬性并不存在;但 JS 語言卻會使用 undefined 。
對象外形( Object Shape )指的是對象已有的屬性與方法的集合,由于該屬性驗證只須在讀取屬性時被觸發,因此只要使用 get 陷阱函數。該陷阱函數會在讀取屬性時被調用,即使該屬性在對象中并不存在,它能接受三個參數:
trapTarget :將會被讀取屬性的對象(即代理的目標對象);
key :需要讀取的屬性的鍵(字符串類型或符號類型);
receiver :操作發生的對象(通常是代理對象)。
相應的Reflect.get()方法同樣擁有這三個參數。進行對象外形驗證的示例代碼:
//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" // 讀取不存在屬性會拋出錯誤 console.log(proxy.nme); // 拋出錯誤使用 has 陷阱函數隱藏屬性
in運算符用于判斷指定對象中是否存在某個屬性,如果對象的屬性名與指定的字符串或符號值相匹配,那么in運算符就會返回true。無論該屬性是對象自身的屬性還是其原型的屬性。
has陷阱函數會在使用in運算符的情況下被調用,控制in運算符返回不同的結果,has陷阱函數會傳入兩個參數:
trapTarget:代理的目標對象;
key:屬性鍵;
Reflect.has()方法接收相同的參數,并向in運算符返回默認的響應結果,用于返回默認響應結果。
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
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97024.html
摘要:方法與代理處理程序的方法相同。使用給目標函數傳入指定的參數。當然,不用反射也可以讀取的值。的例子我們可以理解成是攔截了方法,然后傳入參數,將返回值賦值給,這樣我們就能在需要讀取這個返回值的時候調用。這種代理模式和的代理有異曲同工之妙。 反射 Reflect 當你見到一個新的API,不明白的時候,就在瀏覽器打印出來看看它的樣子。 showImg(https://segmentfault....
摘要:方法與代理處理程序的方法相同。使用給目標函數傳入指定的參數。當然,不用反射也可以讀取的值。的例子我們可以理解成是攔截了方法,然后傳入參數,將返回值賦值給,這樣我們就能在需要讀取這個返回值的時候調用。這種代理模式和的代理有異曲同工之妙。 反射 Reflect 當你見到一個新的API,不明白的時候,就在瀏覽器打印出來看看它的樣子。 showImg(https://segmentfault....
摘要:最近買了深入理解的書籍來看,為什么學習這么久還要買這本書呢主要是看到核心團隊成員及的創造者為本書做了序,作為一個粉絲,還是挺看好這本書能給我帶來一個新的升華,而且本書的作者也非常厲害。 使用ES6開發已經有1年多了,以前看的是阮一峰老師的ES6教程,也看過MDN文檔的ES6語法介紹。 最近買了《深入理解ES6》的書籍來看,為什么學習ES6這么久還要買這本書呢?主要是看到Daniel A...
閱讀 818·2023-04-25 22:13
閱讀 2335·2019-08-30 15:56
閱讀 2217·2019-08-30 11:21
閱讀 650·2019-08-30 11:13
閱讀 2014·2019-08-26 14:06
閱讀 1950·2019-08-26 12:11
閱讀 2282·2019-08-23 16:55
閱讀 530·2019-08-23 15:30