Заместитель прокси для ES5 - PullRequest
14 голосов
/ 26 марта 2019

Можно ли прослушивать изменения свойств без использования Proxy и setInterval?

Для обычных объектов вы можете использовать приведенную ниже функцию, но она работает для всех существующих свойств, но не работает для любых свойств, которые могут быть добавлены после переноса.

function wrap(obj) {
  var target = {};
  Object.keys(obj).forEach(function(key) {
    target[key] = obj[key];
    Object.defineProperty(obj, key, {
      get: function() {
        console.log("Get");
        return target[key];
      },
      set: function(newValue) {
        console.log("Set");
        target[key] = newValue;
      }
    });
  });
}

var obj = {
  a: 2,
  b: 3
};
wrap(obj);

obj.a; // Get
obj.a = 2; // Set
obj.b; // Get
obj.b = 2; // Set
obj.c = 2; // Nothing
obj.c; // Nothing

Если объект является массивом, вы также можете прослушать свойство length и сбросить все функции get и set при его изменении. Это, очевидно, не очень эффективно, так как изменяет свойства каждого элемента всякий раз, когда элемент добавляется или удаляется.

Так что я не думаю, что Object.defineProperty - это ответ.

Причина, по которой я не хочу использовать setInterval, заключается в том, что большие интервалы сделают обертку ненадежной, тогда как небольшие интервалы будут иметь большое влияние на эффективность.

1 Ответ

2 голосов
/ 06 июня 2019

К сожалению, нет, вот почему Прокси были такой большой вещью. На данный момент нет другого способа инициировать код при добавлении свойства к объекту, кроме Proxy.

Как вы говорите, вы можете использовать Object.defineProperty или var a = { get x() {...}, set x(value) {...} }, но не обнаруживать новые свойства.


Большинство фреймворков полагаются на грязную проверку: сравнение объектов по заданному времени. Сроки, где разница в основном.

AngularJS (Angular 1.x) предоставил вам специальные функции для асинхронных операций, таких как $timeout и $http, и это собственный способ прослушивания событий DOM, которые обернут ваши обратные вызовы, и выполнят проверку после вашего кода.

Angular (от Angular 2 до N) использует Zone.js для создания «бегущего контекста» для вашего кода, любой асинхронный обратный вызов перехватывается Zone.js. Это в основном то же решение, что и для AngularJS, но работает автоматически.

React делает нечто подобное, но вместо отслеживания ваших переменных он запускает рендерер и сравнивает, отличается ли сгенерированный DOM (Virtual DOM).

...