ES6 Proxy的學習與理解
問題
前一段時間在位元組跳動時聊到了Proxy。起因是問道Vue中資料繫結的實現,回答通過設定setter和getter實現,問這樣有什麼缺點,答在對物件的屬性的監控方面存在瑕疵,例如通過直接設定陣列下標進行賦值,或者對物件直接進行修改,是無法觀察到的,必須使用Vue.set新增,或者使用Array.prototype.push等方法。
面試官介紹說在Vue3中已經通過Proxy解決了這個問題。Proxy是ES6中新增的內建物件,和Reflect配合功能十分強大。正好今天看到一個問題。
理解
根據MDN的文件,Proxy是對原物件的包裝。可以包裝的內容包括一系列get、set等,值得注意的是getPrototypeOf同樣是一種可以攔截的操作。同時,對於未定義的操作保持原結果。
在instanceof的頁面,可以看到如下示例
function C() {} function D() {} var o = new C(); // true, because: Object.getPrototypeOf(o) === C.prototype o instanceof C;
那麼,在上面那個問題中,既然未定義proxy的getPrototypeOf,那它就該與原物件保持一致。使用以下程式碼進行驗證:
Object.getPrototypeOf(proxy) === Array.prototype //true
進一步思考
那麼,是不是對於一切行為,在不做任何攔截的情況下,就能保證與目標物件的行為完全一致呢?很顯然,這是不可能的。例如
a = {} b = new Proxy(a, {}) console.log(a === b) //false
以及this的指向問題(案例來自阮一峰文章 )
const target = { m: function () { console.log(this === proxy); } }; const handler = {}; const proxy = new Proxy(target, handler); target.m() // false proxy.m()// true
雖然大部分情況下這應該不會成為大的障礙,但遇到錯誤的時候可以從這裡入手尋找問題。