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 =
"Іван"
;