通過調用new proxy()你可以創建一個代理來替代另一個對象(被稱為目標),這個代理對目標對象進行了虛擬,因此該代理與該目標對象表面上可以被當做同一個對象來對待。
創建一個簡單的代理
當你使用Proxy構造器來創建一個代理時,需要傳遞兩個參數:目標對象以及一個處理器,后者是定義了一個或多個陷阱函數的對象。如果未提供陷阱函數,代理會對所有操作采取默認行為。
使用set陷阱函數驗證屬性值
let target = {};
var proxy = new Proxy(target, {
set(trapTarget, key, value, receiver) {
if (!trapTarget.hasOwnProperty(key)) {
if (isNaN(value)) {
throw new Error('Proxy must be a number');
}
}
return Reflect.set(trapTarget, key, value, receiver);
}
})
proxy.count = 1;
console.log(proxy.count);
console.log(target.count);
try {
proxy.anthorName = 'cc';
} catch (err) {
console.log(err.message);
}
使用上述方法可以對添加給對象的屬性值進行驗證,如果值為非數字,就會拋出錯誤。
使用get陷阱函數進行對象外形驗證
在js中,如果讀取一個對象中不存在的屬性時,會顯示undefined,這對於排查問題很不利。使用代理進行對象外形驗證就可以幫你從這個錯誤中拯救出來。
let proxy = new Proxy({}, {
get(trapTarget, key, receiver) {
if (!(key in receiver)) {
throw new Error(`property ${key} not exist`);
}
return Reflect.get(trapTarget, key, receiver);
}
})
proxy.name = 'cc';
try {
console.log(proxy.age);
} catch (error) {
console.log(error.message);
}
//輸出結果
property age not exist
上述代碼對打印的對象屬性進行驗證,如果不存在則拋出一個錯誤。今日頭條的一個面試題
使用has陷阱函數隱藏屬性
in運算符用於判斷指定對象中是否存在某個屬性,如果對象的屬性名與指定的字符串或符號值相匹配,那么in運算符應當返回true,無論該屬性是對象自身的屬性還是原型的屬性。代理允許你使用has陷阱函數來解決這個問題
has陷阱函數會在使用in運算符的情況下被調用,並且會被傳入兩個參數:
- trapTarget:需要讀取屬性的對象(即代理的目標對象)
- key:需要檢查的屬性的鍵(字符串類型或符號類型)Reflect.has()方法接收與之相同的參數並向in運算符返回默認相應結果
let target = {
name: 'cc',
age: 26,
sex: 'man'
}
let proxy = new Proxy(target, {
has(trapTarget, key) {
if (trapTarget.hasOwnProperty(key)) {
return Reflect.has(trapTarget, key);
} else {
return false;
}
}
})
console.log('toString' in proxy);
console.log('name' in proxy);
console.log('age' in proxy);
使用deleteProperty陷阱函數避免屬性被刪除
delete運算符能從指定對象上刪除一個屬性,在刪除成功時返回true,否則返回false
deleteProperty陷阱函數會在使用delete運算符去刪除對象屬性時被調用,並且會被傳入兩個參數:
- trapTarget:需要刪除屬性的對象
- key:需要刪除的屬性的鍵
Reflect.deleteProperty()方法也接受兩個參數,並提供了deleteProperty陷阱函數的默認實現。
let target = {
name: 'target',
value: 42
}
let proxy = new Proxy(target, {
deleteProperty(trapTarg, ke) {
if (ke === 'value') {
return false;
} else {
return Reflect.deleteProperty(trapTarg, ke);
}
}
})
let result = delete proxy.value;
let result1 = delete proxy.name;
console.log(result);
console.log(result1);