Observable
Create a function makeObservable(target)
that “makes the object observable” by returning a proxy.
Here’s how it should work:
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
In other words, an object returned by makeObservable
has the method observe(handler)
.
Whenever a property changes, handler(key, value)
is called with the name and value o the property.
P.S. In this task, please handle only writing to a property. Other operations can be implemented in a similar way. P.P.S. You might want to introduce a global variable or a global structure to store handlers. That’s fine here. In real life, such function lives in a module, that has its own global scope.
The solution consists of two parts:
- Whenever
.observe(handler)
is called, we need to remember the handler somewhere, to be able to call it later. We can store it right in the object, using our symbol as the key. - We need a proxy with
set
trap to call handlers in case of any change.
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";