返回课程

可观察对象

创建一个函数 makeObservable(target),通过返回一个代理来“使对象可观察”。

以下是它的工作原理

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

换句话说,由 makeObservable 返回的对象与原始对象相同,但还具有 observe(handler) 方法,该方法将 handler 函数设置为在任何属性更改时调用。

每当属性更改时,都会调用 handler(key, value),其中包含属性的名称和值。

附注:在本任务中,请只关注写入属性。其他操作可以以类似的方式实现。

该解决方案包含两个部分。

  1. 每当调用 .observe(handler) 时,我们需要将处理程序存储在某个地方,以便以后能够调用它。我们可以使用我们的符号作为属性键,将处理程序直接存储在对象中。
  2. 我们需要一个带有 set 陷阱的代理,以便在发生任何更改时调用处理程序。
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";