Вопрос по javascript – Слушатель для изменения значения свойства в объекте JavaScript

19

Просматривая документацию по javascript, я обнаружил, что следующие две функции объекта javascript выглядят интересно:

.watch - Следит за свойством, которому должно быть присвоено значение, и запускает функцию, когда это происходит.
.unwatch - Удаляет точку наблюдения, установленную методом watch.

Пример использования:

o = { p: 1 };
o.watch("p", function (id,oldval,newval) {
    console.log("o." + id + " changed from " + oldval + " to " + newval)
    return newval;
});

Всякий раз, когда мы меняем значение свойства "p", эта функция срабатывает.

o.p = 2;   //logs: "o.p changed from 1 to 2"

Я работаю над JavaScript в течение последних нескольких лет и никогда не использовал эти функции.
Может кто-нибудь, пожалуйста, приведите несколько хороших вариантов использования, где эти функции пригодятся?

Они доступны только для браузеров на базе Gecko, таких как Mozilla Firefox. Internet Explorer предоставляет похожий метод для объектов, называемый onpropertychange. Ionuț G. Stan

Ваш Ответ

5   ответов
4

Object.watch and Object.observe are both deprecated and should not be used. onPropertyChange is a DOM element event handler that only works in some versions of IE. Object.defineProperty allows you to make an object property immutable, which would allow you to detect attempted changes, but it would also block any changes. Defining setters and getters works, but it requires a lot of setup code and it does not work well when you need to delete or create new properties.

Сегодня,you can now use the полномочие объект отслеживать (и перехватывать) изменения, внесенные в объект. Он специально создан для того, что пытается сделать ОП. Вот основной пример:

var targetObj = {};
var targetProxy = new Proxy(targetObj, {
  set: function (target, key, value) {
      console.log(`${key} set to ${value}`);
      target[key] = value;
      return true;
  }
});

targetProxy.hello_world = "test"; // console: 'hello_world set to test'

Единственные недостаткиProxy Объектом являются:

The Proxy object is not available in older browsers (such as IE11) and the polyfill cannot fully replicate Proxy functionality. Proxy objects do not always behave as expected with special objects (e.g., Date) -- the Proxy object is best paired with plain Objects or Arrays.

Если вам нужно наблюдать изменения, внесенные вnested object, то вам нужно использовать специализированную библиотеку, такую какНаблюдаемый Тонкий (который я написал). Это работает так:

var test = {testing:{}};
var p = ObservableSlim.create(test, true, function(changes) {
    console.log(JSON.stringify(changes));
});

p.testing.blah = 42; // console:  [{"type":"add","target":{"blah":42},"property":"blah","newValue":42,"currentPath":"testing.blah",jsonPointer:"/testing/blah","proxy":{"blah":42}}]
8

пример, вы можете проверить, что что-то является целым числом:

obj.watch('count', function(id, oldval, newval) {
    var val = parseInt(newval, 10);
    if(isNaN(val)) return oldval;
    return val;
});

Вы можете использовать его для проверки длины строки:

obj.watch('name', function(id, oldval, newval) {
    return newval.substr(0, 20);
});

However, these are only available in the latest versions of the SpiderMonkey javascript engine.  Прекрасно, если вы используете Jaxer или встраиваете движок SpiderMonkey, но пока не доступен в вашем браузере (если вы не используете FF3).

Error: User Rate Limit Exceeded
1

События Javascript Propery библиотека. Это небольшая библиотека, расширяющаясяObject.defineProperty с некоторыми участниками событий, которые я сделал недавно. Добавляет несколькоon[event] свойства, которые могут быть использованы какon[event] свойства HTML-объектов. Он также имеет простую проверку типа, которая вызываетonerror событие, если оно терпит неудачу.

Взяв ваш код, вы получите что-то вроде этого:

var o = {}
Object.defineProperty(o, "p", {
    value:1,
    writable:true,
    onchange:function(e){
        console.log("o." + e.target + " changed from " + e.previousValue + " to " + e.returnValue);
    }
})
0

Object.prototype.startWatch = function (onWatch) {

    var self = this;

    if (!self.watchTask) {
        self.oldValues = [];

        for (var propName in self) {
            self.oldValues[propName] = self[propName];
        }


        self.watchTask = setInterval(function () {
            for (var propName in self) {
                var propValue = self[propName];
                if (typeof (propValue) != 'function') {


                    var oldValue = self.oldValues[propName];

                    if (propValue != oldValue) {
                        self.oldValues[propName] = propValue;

                        onWatch({ obj: self, propName: propName, oldValue: oldValue, newValue: propValue });

                    }

                }
            }
        }, 1);
    }



}

var o = { a: 1, b: 2 };

o.startWatch(function (e) {
    console.log("property changed: " + e.propName);
    console.log("old value: " + e.oldValue);
    console.log("new value: " + e.newValue);
});
8

Проверять, выписыватьсяObject.defineProperty а также Object.prototype.\__defineGetter__ (или же\__defineSetter__ ) чтобы увидеть, куда движется эта функциональность.

Object.defineProperty должен быть доступен во всех современных браузерах очень скоро.

Похожие вопросы