目錄
get 和 set 捕獲器詳解
為什么要用 Reflect?
使用語法間接調用內部方法
使用 Reflect 直接調用內部方法
對比總結:
Reflect API 及其與 Proxy 的配合
Proxy 的典型應用場景
Proxy 是 ES6 引入的一種元編程特性。它允許創建一個代理對象來包裝目標對象,并攔截對目標對象的各種操作(如屬性讀取、寫入、枚舉、函數調用等),從而可以自定義這些操作的行為。語法上,new Proxy(target, handler)
接受兩個參數:第一個是要代理的目標對象,第二個是包含各種“捕獲器”(traps)的處理器對象。例如,get
捕獲器可以攔截屬性讀取操作,set
捕獲器攔截屬性寫入操作等等。如果處理器中定義了對應的捕獲器,就會在操作發生時被觸發;否則,操作會默認直接作用于目標對象。Proxy 機制被廣泛用于框架和庫中,比如 Vue3 的響應式系統就是基于 Proxy 實現的
get 和 set 捕獲器詳解
在 handler
中可以定義不同的捕獲器來攔截操作。其中最常用的是 get
和 set
:
-
get(target, property, receiver):攔截屬性讀取操作,當訪問
proxy.property
時觸發。參數說明為-
target
:目標對象(被代理的原始對象)。 -
property
:被讀取的屬性名。 -
receiver
:通常是當前訪問該屬性時的this
值(通常就是代理對象本身,或者如果繼承自該代理的對象,則是繼承對象)。如果該屬性是一個 getter,那么receiver
就是執行 getter 時的this
。
-
-
set(target, property, value, receiver):攔截屬性寫入操作,當執行
proxy.property = value
時觸發。參數說明為target
:目標對象。-
property
:被寫入的屬性名。 -
value
:寫入的值。 -
receiver
:與get
類似,對應 setter 被調用時的this
。
set
捕獲器應該返回一個布爾值,true
表示寫入成功,false
表示失敗(失敗時會拋出TypeError
)
-
例如,以下代碼演示了一個帶有 get
和 set
捕獲器的 Proxy 用法:
const person = {name: "張三",get aliasName() {return this.name + "handsome";},
};
const proxyPerson = new Proxy(person, {get(target, key, receiver) {console.log("get", key);return Reflect.get(target, key, receiver);},set(target, key, value) {console.log(`set ${key} = ${value}`);return Reflect.set(target, key, value);},
});
console.log(person.aliasName); // 張三handsome
console.log(proxyPerson.aliasName); // 輸出:get aliasName \n 張三handsome
proxyPerson.name = "李四"; // 輸出:set name = 李四
console.log(proxyPerson.aliasName); // 輸出:get aliasName \n 李四handsome
上例中&#