122

Please note that Object.Watch and Object.Observe are both deprecated now (as of Jun 2018).


I was looking for an easy way to monitor an object or variable for changes, and I found Object.watch(), that's supported in Mozilla browsers, but not IE. So I started searching around to see if anyone had written some sort of equivalent.

About the only thing I've found has been a jQuery plugin, but I'm not sure if that's the best way to go. I certainly use jQuery in most of my projects, so I'm not worried about the jQuery aspect...

Anyway, the question: Can someone show me a working example of that jQuery plugin? I'm having problems making it work...

Or, does anyone know of any better alternatives that would work cross browser?

Update after answers:

Thanks everyone for the responses! I tried out the code posted here: http://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html

But I couldn't seem to make it work with IE. The code below works fine in Firefox, but does nothing in IE. In Firefox, each time watcher.status is changed, the document.write() in watcher.watch() is called and you can see the output on the page. In IE, that doesn't happen, but I can see that watcher.status is updating the value, because the last document.write() call shows the correct value (in both IE and FF). But, if the callback function isn't called, then that's kind of pointless... :)

Am I missing something?

var options = {'status': 'no status'},
watcher = createWatcher(options);

watcher.watch("status", function(prop, oldValue, newValue) {
  document.write("old: " + oldValue + ", new: " + newValue + "<br>");
  return newValue;
});

watcher.status = 'asdf';
watcher.status = '1234';

document.write(watcher.status + "<br>");
4

8 回答 8

114

(很抱歉交叉发布,但我对类似问题给出的这个答案在这里很好用)

不久前,我为此创建了一个小object.watch shim。它适用于 IE8、Safari、Chrome、Firefox、Opera 等。

于 2009-08-13T05:32:43.933 回答
20

该插件仅使用计时器/间隔来重复检查对象的更改。也许足够好,但我个人希望作为观察者更直接。

watch这是将/unwatch引入 IE的尝试: http ://webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html 。

它确实改变了 Firefox 添加观察者的方式的语法。代替 :

var obj = {foo:'bar'};
obj.watch('foo', fooChanged);

你做:

var obj = {foo:'bar'};
var watcher = createWatcher(obj);
watcher.watch('foo', fooChanged);

不是那么甜蜜,但作为观察者,您会立即收到通知。

于 2009-06-22T21:16:33.277 回答
16

这个问题的答案有点过时了。Object.watchObject.observe都已弃用,不应使用。

今天,您现在可以使用代理对象来监视(和拦截)对对象所做的更改。这是一个基本示例:

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

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

如果您需要观察对嵌套对象所做的更改,那么您需要使用专门的库。我发布了Observable Slim,它的工作原理是这样的:

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}}]
于 2018-06-14T05:04:59.947 回答
13

当前答案

使用新的Proxy对象,它可以观察其目标的变化。

let validator = {
    set: function(obj, prop, value) {
        if (prop === 'age') {
            if (!Number.isInteger(value)) {
                throw new TypeError('The age is not an integer');
            }
            if (value > 200) {
                throw new RangeError('The age seems invalid');
            }
        }

        // The default behavior to store the value
        obj[prop] = value;

        // Indicate success
        return true;
    }
};

let person = new Proxy({}, validator);

person.age = 100;
console.log(person.age); // 100
person.age = 'young'; // Throws an exception
person.age = 300; // Throws an exception

2015年的旧答案

您可以使用ES7 中的 Object.observe()这是一个polyfill。但是Object.observe() 现在被取消了。对不起人!

于 2013-06-27T14:54:22.510 回答
7

请注意,在 Chrome 36 及更高版本中您也可以使用Object.observe。这实际上是未来 ECMAScript 标准的一部分,而不是像 Mozilla 的Object.watch.

Object.observe仅适用于对象属性,但比Object.watch(用于调试目的,而不是生产用途)性能要高得多。

var options = {};

Object.observe(options, function(changes) {
    console.log(changes);
});

options.foo = 'bar';
于 2014-07-16T12:27:29.783 回答
4

您可以使用Object.defineProperty

看房bar_foo

Object.defineProperty(foo, "bar", {
  get: function (val){
      //some code to watch the getter function
  },

  set: function (val) {
      //some code to watch the setter function
  }
})
于 2017-01-20T15:03:34.380 回答
1

我在我的一个项目中使用了 Watch.js。它工作正常。使用这个库的主要优点之一是:

“有了 Watch.JS,你就不必改变你的开发方式了。”

示例如下

//defining our object however we like
var ex1 = {
	attr1: "initial value of attr1",
	attr2: "initial value of attr2"
};

//defining a 'watcher' for an attribute
watch(ex1, "attr1", function(){
	alert("attr1 changed!");
});

//when changing the attribute its watcher will be invoked
ex1.attr1 = "other value";
<script src="https://cdn.jsdelivr.net/npm/melanke-watchjs@1.5.0/src/watch.min.js"></script>

就这么简单!

于 2018-12-10T12:05:56.443 回答
-2

我也认为现在最好的解决方案是使用 Watch.JS,在这里找到一个很好的教程:Listen/Watch for object or array changes in Javascript (Property changed event on Javascript objects)

于 2013-07-14T15:33:30.597 回答