最近在項目裏使用了 Proxy,遇到一些問題記錄一下javascript
簡單來講 Proxy 是對對象
設置一個攔截,直接上代碼java
let obj = {
attr: 1
};
// 對 obj 進行攔截
obj = new Proxy(obj, {
get: function (target, key, receiver) {
//若是 obj 有這個屬性,則直接返回
if(key in target) {
return target[key];
}
//若是 obj 沒有這個屬性,則統一返回 '沒有這個值'
return '沒有這個值';
},
set: function (target, key, value, receiver) {
// 想設置對象屬性,直接返回(不讓設置)
return true;
}
});
// 使用
console.log(obj.attr); // 輸出 1
console.log(obj.abc); // 輸出 '沒有這個值',
obj.attr = 2;//
console.log(obj.attr); // 輸出 1, 不能設置對象屬性
複製代碼
能夠進行的攔截類型不止 get, set
,還有不少,例如:(來自阮一峯老師的書 ES6 Proxy):es6
如上這些都是介紹都是直接拷貝的 阮一峯老師的書 ES6 Proxychrome
一、攔截時的 this
指向問題 阮老師書裏也有說起數組
在攔截方法裏,this
指向 Proxy 對象,因此在調用原對象的方法時,須要注意,直接看代碼瀏覽器
let div = document.querySelector('div'); // 隨便拿一個頁面的 div, 對他進行代理
// 第一種代理方法
let divProxy = new Proxy(div, {
get: function (target, key, receiver) {
// 訪問這個 div 的任何屬性,都直接返回
return target[key];
}
});
// 調用 div 的 querySelector 方法,拿他下邊的 a 標籤
console.log(divProxy.querySelector('a')); // chrome 上會報錯:Uncaught TypeError: Illegal invocation
複製代碼
如上的代碼,猜想由於 querySelector 方法內部有訪問 this
指向,致使報錯。修改成以下代碼,則能夠修復這個問題:babel
let div = document.querySelector('div'); // 隨便拿一個頁面的 div, 對他進行代理
// 第二種代理方法
let divProxy = new Proxy(div, {
get: function (target, key, receiver) {
if( !!target[key] && !!target[key].bind) {
// 使用 bind 綁定 this 指向
return target[key].bind(target);
} else {
return target[key];
}
}
});
console.log(divProxy.querySelector('a')); // <a href='https://t.tt'>來買呀</a>
複製代碼
另外還有一個問題,經過代理設置對象屬性時,也會有問題相同的,看代碼吧app
let div = document.querySelector('div');
let divProxy = new Proxy(div, {});
// 設置 div 的 innerHTML 屬性,設置對象屬性默認實際上是調用 `div.innerHTML.__defineSetter__` 方法
divProxy.innerHTML = '<a href="https://t.tt">來買呀</a>'; //chrome 報錯: Uncaught TypeError: Illegal invocation
複製代碼
直接上解決辦法函數
let div = document.querySelector('div');
let divProxy = new Proxy(div, {
// 攔截全部的 set 行爲
set: function (target, key, value, receiver) {
if(key in target) {
target[key] = value; // 直接調用原對象屬性進行設置(target[key])
}
return true;
}
});
divProxy.innerHTML = '<a href="https://t.tt">來買呀</a>';
複製代碼
通常 Proxy
會和 Reflect
一塊兒使用,本文不作介紹了,直接上阮老師的書;ui
JavaScript 的語法愈來愈規範,以前的一些坑,新的標準規範也開始慢慢填,加上babel
的普及使用,咱們能夠多多擁抱新語法、特性,簡潔代碼,愉悅本身。