40 lines
1.1 KiB
Markdown
40 lines
1.1 KiB
Markdown
The solution consists of two parts:
|
|
|
|
1. Whenever `.observe(handler)` is called, we need to remember the handler somewhere, to be able to call it later. We can store handlers right in the object, using our symbol as the property key.
|
|
2. We need a proxy with `set` trap to call handlers in case of any change.
|
|
|
|
```js run
|
|
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";
|
|
```
|