为什么不推荐使用Object.observe()

时间:2016-03-28 08:16:18

标签: javascript

有替代方法吗?

还有另一种方法可以在对象中进行更改检测吗?

有代理方法,但任何人都可以告诉我如何使用代理实现此目的:

{{1}}

3 个答案:

答案 0 :(得分:44)

你可以通过getter和setter实现这一目标。

var obj = {
  get foo() {
    console.log({ name: 'foo', object: obj, type: 'get' });
    return obj._foo;
  },
  set bar(val) {
    console.log({ name: 'bar', object: obj, type: 'set', oldValue: obj._bar });
    return obj._bar = val;
  }
};

obj.bar = 2;
// {name: 'bar', object: <obj>, type: 'set', oldValue: undefined}

obj.foo;
// {name: 'foo', object: <obj>, type: 'get'}

或者,在支持Proxies的浏览器中,您可以编写更通用的解决方案。

var obj = {
  foo: 1,
  bar: 2
};

var 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.bar = 2;
// {type: 'set', target: <obj>, prop: 'bar', value: 2}

proxied.foo;
// {type: 'get', target: <obj>, prop: 'bar'}

答案 1 :(得分:12)

@Dan Prince解决方案是正确的。它应该是第一选择。

如果你想支持相当老的浏览器,我建议你去填充或使用IE 9支持的 Object.defineProperties API

var obj = Object.defineProperties({}, {
    "foo":{
        get:function(){
            console.log("Get:"+this.value);
        },
        set:function(val){
            console.log("Set:"+val);
            this.value = val;
        }
    },

    "bar":{         
        get:function(){
            console.log("Get:"+this.value);
        },
        set:function(val){
            console.log("Set:"+val);
            this.value = val;
        }
    }
 });

答案 2 :(得分:11)

免责声明:我是下面建议的object-observer库的作者。

我不会选择getter / setter解决方案 - 它很复杂,不可扩展且无法维护。 Backbone以这种方式进行双向绑定,并使样板正常运行的样板是一段代码。

代理是实现所需内容的最佳方式,只需在上面的示例中添加一些回调注册和管理,并在更改时执行它们。

关于polyfill库:其中一些/大多数使用“脏检查”或轮询技术实现 - 效率低,性能不高。偶尔,这是上面Nirus指出的polyfill的情况。

我建议选择一些通过Proxies进行观察的库。那里有一些,object-observer就是其中之一:完全用这个用例编写,利用原生代理,提供深层树观察等。