Observable
プロキシを返して「オブジェクトをオブザーバブルにする」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
によって返されるオブジェクトは元のオブジェクトと同じですが、任意のプロパティの変更時に呼び出されるhandler
関数を設定するobserve(handler)
メソッドも追加されています。
プロパティが変更されるたびに、handler(key, value)
はプロパティの名前と値で呼び出されます。
P.S. このタスクでは、プロパティへの書き込みのみを処理してください。他の操作は同様の方法で実装できます。
解決策は2つの部分で構成されています。
.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";