Observable
Create una funzione makeObservable(target)
che “rende l’oggetto osservabile” ritornandone un proxy.
Ecco come dovrebbe funzionare:
function makeObservable(target) {
/* il vostro codice */
}
let user = {};
user = makeObservable(user);
user.observe((key, value) => {
alert(`SET ${key}=${value}`);
});
user.name = "John"; // alerts: SET name=John
In altre parole, un oggetto ritornato da makeObservable
equivale a quello originale, ma possiede il metodo observe(handler)
che imposta la funzione handler
per essere invocata quando una qualsiasi proprietà cambia.
Quando una proprietà verrà modificata, handler(key, value)
verrà invocato con il nome ed il valore della proprietà.
P.S. In questo task, gestite solamente la scrittura della proprietà. Le altre operazioni possono essere implementate in maniera simile.
La soluzione consiste di due parti:
- Quando
.observe(handler)
viene invocato, dobbiamo memorizzare l’handler da qualche parte, per poter essere in grado di invocarlo più tardi. Possiamo memorizzare gli handler nell’oggetto, utilizzando un symbol come chiave della proprietà. - Abbiamo bisogno di un proxy con la trappola
set
per poter invocare gli handlers in caso di cambiamenti.
let handlers = Symbol('handlers');
function makeObservable(target) {
// 1. Inizializziamo lo store per gli handlers
target[handlers] = [];
// Memorizziamo l'handler nell'array per poterlo invocare successivamente
target.observe = function(handler) {
this[handlers].push(handler);
};
// 2. Creiamo un proxy per gestire le modifiche
return new Proxy(target, {
set(target, property, value, receiver) {
let success = Reflect.set(...arguments); // inoltriamo l'operazione all'oggetto
if (success) { // se non è stato generato alcun errore durante il cambiamento della proprietà
// invochiamo tutti gli 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";