适用于所有浏览器的Object.watch()吗?


118

请注意,Object.WatchObject.Observe现在都弃用(如2018年6月的)。


我一直在寻找一种监视对象或变量更改的简便方法,我发现Object.watch()Mozilla浏览器支持,但IE不支持。所以我开始四处搜寻,看看是否有人写过类似的东西。

我唯一发现的就是jQuery插件,但我不确定这是否是最好的方法。我当然在我的大多数项目中都使用jQuery,所以我不必担心jQuery方面的问题。

无论如何,问题是:有人可以向我展示该jQuery插件的有效示例吗?我在使其工作时遇到问题...

还是有人知道跨浏览器更好的替代方法吗?

回答后更新

感谢大家的回应!我尝试了发布在此处的代码:http : //webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html

但是我似乎无法使其与IE一起使用。下面的代码在Firefox中可以正常工作,但在IE中则不起作用。在Firefox中,每次watcher.status更改都会调用document.write()in watcher.watch(),您可以在页面上看到输出。在IE中,这不会发生,但是我可以看到它watcher.status正在更新值,因为最后一次document.write()调用显示了正确的值(在IE和FF中)。但是,如果没有调用回调函数,那是没有意义的... :)

我想念什么吗?

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>");

2
IIRC您可以在IE中使用onPropertyChange
scunliffe 2009年

1
用alert()替换document.write()。它应该工作正常。
Ionuț G. Stan,

Answers:


113

(对于交叉发布,我们深表歉意,但是我对类似问题的回答在这里很好用)

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


10
对于那些不是JS大师的人来说,如何使用它以及如何在内部工作是一个很好的解释,谢谢。
maraujop 2011年


jsfiddle.net/kSWxP提示:使用Firefox(Chrome中未打印后一个声明)
Mars Robertson


我知道想法Object.defineProperty()存在。我最终查看了MDN参考,以了解其工作原理。
jumpnett

19

该插件仅使用计时器/间隔重复检查对象的更改。也许足够好,但就我个人而言,我想作为观察员更加直接。

这是尝试将IE 引入watch/ 的尝试unwatchhttp : //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);

不那么甜美,但作为观察者,您会立即得到通知。


是的,请观看那些时间戳记...无需投票,也crescentfresh向该帖子添加了更多信息,即使它是相同的链接也是如此。同时,我尝试了在该页面上找到的代码,但仍然看到问题。我可能会忽略一些东西。我已经更新了我的原始帖子,更多信息...
SeanW

13

这个问题的答案有点过时了。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}}]

12

当前答案

使用新的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()这是一个保鲜纸。但是Object.observe()现在被取消了。抱歉!


嗯,我无法让此polyfill在ios Safari中使用。我收到错误消息:undefined不是一个函数(评估'Object.observe(a.imgTouch,function(a){console.debug(“ lastX:” + a)})'))
infomofo

@infomofo您好,您想在项目页面上打开一个问题,其中提供您可以提供的所有详细信息吗?我尚未在iOS上对其进行测试,但我将调查问题。
MaxArt

6

请注意,在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';

1
与2018年一样,此版本已弃用,不再受所有主要浏览器的支持
Sergei Panfilov

4

您可以使用Object.defineProperty

看属性barfoo

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

  set: function (val) {
      //some code to watch the setter function
  }
})

这很棒!但我会稍作修改:)不覆盖原始的二传手。我会引用foo._someObject = foo.someObject
平静鸟

简单而
优雅

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>

就这么简单!


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.