概述
Proxy
可以了解成,在目标對象之前架設一層“攔截”,外界對該對象的通路,都必須先通過這層攔截,是以提供了一種機制,可以對外界的通路進行過濾和改寫。
Proxy
這個詞的原意是代理,用在這裡表示由它來“代理”某些操作,可以譯為“代理器”。
而
Object.defineProperty
是使用的資料劫持:直接在一個對象上定義一個新屬性,或者修改一個對象的現有屬性,并傳回此對象。
在通路或者修改對象的某個屬性時,通過一段代碼攔截這個行為,進行額外的操作或者修改傳回結果。資料劫持最典型的應用 -----> 雙向的資料綁定(一個常用的面試題),
-
利用Vue 2.x
,并且把内部解耦為Object.defineProperty()
,Observer
, 并使用Dep
相連Watcher
-
在Vue
版本之後改用3.x
進行實作Proxy
Proxy
與 Object.defineProperty
的對比
Proxy
Object.defineProperty
-
Object.defineProperty
- 隻能監聽對象(
),不能監聽數組的變化,無法觸發Object
push
pop
shift
unshift
splice
sort
。reverse
- 必須周遊對象的每個屬性
- 隻能劫持目前對象屬性,如果想深度劫持,必須深層周遊嵌套的對象
- 隻能監聽對象(
"use strict"
let obj = {};
let value = 1
Object.defineProperty(obj, 'listenA', {
writable: true, //可修改
enumerable: true, // 可枚舉 for...in... Object.keys()
configurable: true, // 可配置,可删除
get: () => value,
set: val => {
console.log(`set obj.listenA .. ${val}`);
value = val
},
});
obj.listenA = 2 //set obj.listenA .. 2
console.log(obj.listenA) // 2
Proxy
- 可以直接監聽對象而非屬性
- 可以直接監聽數組的變化
// 代理整個對象
let proxyObj = new Proxy({}, {
get: (target, key, receiver) => {
console.log(`getting ${key}!`);
return target[key];
},
set: (target, key, value, receiver) => {
console.log(target, key, value, receiver);
return target[key] = value;
},
});
proxyObj.val = 1; // {} val 1 {}
proxyObj.val; // getting val!
//代理數組
let proxyArr = new Proxy([], {
get: (target, key, receiver) => {
console.log(`getting ${key}!`);
return target[key];
},
set: (target, key, value, receiver) => {
console.log(target, key, value, receiver);
return (target[key] = value);
},
});
proxyArr[0] = 1; // {} val 1 {}
console.log(proxyArr[0]); // getting val! // 1
console.log(proxyArr); // [1]