Как отследить изменение в объекте?

175
31 августа 2018, 06:10

Как в javascript можно отследить изменение свойства объекта и при изменении вызвать callBack?
Например: obj.prop = true;
При изменении obj.prop на false должна вызываться функция next()

Answer 1

Вариант через Proxy c get и set

Работает с вложенными объектами, а так же срабатывает get при удалении свойств объекта или когда происходит переход во вложенный объект. В примере легко понять что и где меняется, а так же обрабатывать изменения так как вам необходимо (вместо console.log).

Пример

let obj = { 
  foo: 1, 
  bar: 2, 
  items: { 
    firstProperty: 1, 
    secondProperty: 2 
  } 
}; 
 
let proxied = new Proxy(obj, { 
  get: function(target, prop) { 
    console.log({ 
      type: "get", 
      target, 
      prop 
    }); 
    return Reflect.get(target, prop); 
  }, 
  set: function(target, prop, value) { 
    console.log({ 
      type: "set", 
      target, 
      prop, 
      value 
    }); 
    return Reflect.set(target, prop, value); 
  } 
}); 
 
proxied.items.firstProperty = 3; 
//{ type: 'get', target: { foo: 1,bar: 2, items: { firstProperty: 1, secondProperty: 2 } }, prop: 'items' } 
//{ type: 'set', target: { foo: 1, bar: 2, items: { firstProperty: 3, secondProperty: 2 } }, prop: 'bar',  value: 2 } 
 
proxied.bar = 2; 
//{ type: 'set', target: { foo: 1, bar: 2 }, prop: 'bar', value: 2 } 
 
proxied.asd = 3; 
//{ type: 'set', target: { foo: 1, bar: 2 }, prop: 'asd', value: 3 } 
 
proxied.foo; 
//{ type: 'get', target: { foo: 1, bar: 2, asd: 3 }, prop: 'foo' } 
 
proxied.foo = 3; 
//{ type: 'set', target: { foo: 1, bar: 2, asd: 3 }, prop: 'foo', value: 3 } 
 
delete proxied.foo; 
//{ type: 'get', target: { bar: 2, asd: 3 }, prop: Symbol(util.inspect.custom) } ... 
 
console.log(obj);

object.watch и object.observe являются устаревшими или экспериментальными и не такими гибкими на данный момент.

Answer 2

1 вариант: использовать сеттер/геттер

const obj = {
   _prop: false,
   get prop() { return this._prop }
   set prop(value) {
      // тут можно еще что-то вызвать
      this._prop = value
   }
}

2 вариант: использовать proxy

const handler = {
  set: function(obj, prop, value) {
    if(prop === 'prop') {
      console.log('prop was changed');
    }
    // Стандартное сохранение значения
    obj[prop] = value;
  }
};
const test = new Proxy({prop: true}, handler);
test.prop = false;
test.prop = true;

3 вариант: object observe ( эксперимент es7 )

const obj = {prop: true};
Object.observe(obj, function(changes) {
  if(changes[0].name === 'prop') {
    console.log('prop was changed');
  }
});
obj.prop = false;

4 вариант: просто написать функцию, в которой это св-во меняется и использовать только ее

function changeObjProp (obj, value, callback) {
  obj.prop = value;
  return callback();
}
const test = {prop: false}
changeObjProp(test, true, () => console.log('prop was changed'));
READ ALSO
React приложение. Cross origin запрос

React приложение. Cross origin запрос

Решил попробовать Реакт

162
Почему сортировка по цене не работает?

Почему сортировка по цене не работает?

В методе sortProductsByPrice (sortOrder) сортировка не работает, когда я удаляю или добавляю продукты в dom при помощи слушателей(buttAddaddEventListener,buttDelete

168
Работа с функциями. как передать коллекцию в функции? [закрыт]

Работа с функциями. как передать коллекцию в функции? [закрыт]

Как реализовать данный код? Как сделать такие функции? (данный код менять нельзя)

171