Observable
Створіть функцію makeObservable(target)
, яка “робить об’єкт доступним для спостереження”, повертаючи проксі.
Ось як це має працювати:
function makeObservable(target) {
/* ваш код */
}
let user = {};
user = makeObservable(user);
user.observe((key, value) => {
alert(`SET ${key}=${value}`);
});
user.name = "Іван"; // сповіщає: SET name=Іван
Іншими словами, об’єкт, повернутий makeObservable
, такий же, як оригінальний, але також має метод observe(handler)
, який встановлює функцію handler
для виклику при будь-якій зміні властивості.
Щоразу, коли властивість змінюється, викликається handler(key, value)
з назвою та значенням властивості.
P.S. У цьому завданні подбайте лише про запис у властивість. Подібним чином можна реалізувати й інші операції.
Рішення складається з двох частин:
- Щоразу, коли викликається
.observe(handler)
, нам потрібно десь запам’ятати обробник, щоб мати можливість викликати його пізніше. Ми можемо зберігати обробники прямо в об’єкті, використовуючи наш символ як ключ властивості. - Нам потрібен проксі з пасткою
set
для виклику обробників у разі будь-яких змін.
let handlers = Symbol('handlers');
function makeObservable(target) {
// 1. Ініціалізуємо сховище обробників
target[handlers] = [];
// Збережемо функцію-обробник в масиві для майбутніх викликів
target.observe = function(handler) {
this[handlers].push(handler);
};
// 2. Створимо проксі для обробки змін
return new Proxy(target, {
set(target, property, value, receiver) {
let success = Reflect.set(...arguments); // перенаправимо операцію на об’єкт
if (success) { // якщо під час запису властивості не було помилок
// викличемо всі обробники
target[handlers].forEach(handler => handler(property, value));
}
return success;
}
});
}
let user = {};
user = makeObservable(user);
user.observe((key, value) => {
alert(`SET ${key}=${value}`);
});
user.name = "Іван";