可觀察物件
建立一個函式 makeObservable(target)
,透過傳回一個代理來「讓物件可觀察」
以下是它的運作方式
function makeObservable(target) {
/* your code */
}
let user = {};
user = makeObservable(user);
user.observe((key, value) => {
alert(`SET ${key}=${value}`);
});
user.name = "John"; // alerts: SET name=John
換句話說,makeObservable
傳回的物件就像原始物件一樣,但它還有一個方法 observe(handler)
,這個方法會設定 handler
函式,以便在任何屬性變更時呼叫它。
每當屬性變更時,handler(key, value)
就會使用屬性的名稱和值來呼叫。
附註:在此任務中,請僅注意寫入屬性。其他操作可以以類似的方式實作。
此解決方案包含兩個部分
- 每當呼叫
.observe(handler)
時,我們需要記住某處的處理常式,才能在稍後呼叫它。我們可以使用我們的符號作為屬性金鑰,將處理常式儲存在物件中。 - 我們需要一個具有
set
陷阱的代理程式,以便在發生任何變更時呼叫處理常式。
let handlers = Symbol('handlers');
function makeObservable(target) {
// 1. Initialize handlers store
target[handlers] = [];
// Store the handler function in array for future calls
target.observe = function(handler) {
this[handlers].push(handler);
};
// 2. Create a proxy to handle changes
return new Proxy(target, {
set(target, property, value, receiver) {
let success = Reflect.set(...arguments); // forward the operation to object
if (success) { // if there were no error while setting the property
// call all handlers
target[handlers].forEach(handler => handler(property, value));
}
return success;
}
});
}
let user = {};
user = makeObservable(user);
user.observe((key, value) => {
alert(`SET ${key}=${value}`);
});
user.name = "John";