Observable 만들기
프락시를 반환해 ‘객체를 observable 하게 만들어주는’ 함수 makeObservable(target)
를 만들어보세요.
최종 결과는 아래 조건을 만족해야 합니다.
function makeObservable(target) {
/* 여기에 코드를 작성하세요. */
}
let user = {};
user = makeObservable(user);
user.observe((key, value) => {
alert(`SET ${key}=${value}`);
});
user.name = "John"; // alerts: SET name=John
makeObservable
가 반환하는 객체는 기존 객체와 동일하지만 프로퍼티가 변경될 때 호출되는 함수인 handler
를 설정해주는 메서드 observe(handler)
가 있어야 합니다.
프로퍼티가 변경될 때마다 프로퍼티 키와 값을 인수로 받는 메서드 handler(key, value)
가 호출되어야 하죠.
참고: 이 문제에선 프로퍼티에 값을 쓰려는 경우만 고려해서 답을 작성해보세요. 읽기 등의 동작은 유사한 방법을 사용해 구현할 수 있습니다.
해답은 크게 두 부분으로 구성됩니다.
.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 = "John";