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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/36258502/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 18:49:29  来源:igfitidea点击:

Why has Object.observe() been deprecated

javascript

提问by Shad

Is there an alternative approach?

有没有替代方法?

Is there another way to do change detection in object?

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

There is the Proxy method, but can anyone tell me how can I achieve this using Proxy:

有 Proxy 方法,但谁能告诉我如何使用 Proxy 实现这一点:

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

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

obj.baz = 2;
// [{name: 'baz', object: <obj>, type: 'add'}]

obj.foo = 'hello';
// [{name: 'foo', object: <obj>, type: 'update', oldValue: 0}]

回答by Dan Prince

You can achieve this with getters and setters.

您可以使用 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'}

Alternatively, in a browser with support for Proxies, you can write a more generic solution.

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

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'}

回答by GullerYA

Disclaimer: I'm the author of the object-observerlibrary suggested below.

免责声明:我是下面建议的对象观察者库的作者。

I'd not go with getters/setters solution - it's complicated, not scalable and not maintainable. Backbone did their two-way binding that way and the boilerplate to get it working correctly was quite a piece of a code.

我不会使用 getter/setter 解决方案 - 它很复杂,不可扩展且不可维护。Backbone 以这种方式进行了双向绑定,而使其正常工作的样板代码是一段相当长的代码。

Proxies is the best way to achieve what you need, just add to the examples above some callbacks registration and management and execute them upon a changes.

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

As regarding to the polyfill libraries: some/most of these implemented utilizing 'dirty check' or polling technique - not efficient, not performant. Occasionally, this is the case of the polyfill pointed out by Nirus above.

至于 polyfill 库:其中一些/大部分使用“脏检查”或轮询技术实现 - 效率不高,性能不高。有时,这是 Nirus 上面指出的 polyfill 的情况。

I'd recommend to pick up some library that does observation via Proxies. There are a few out there, object-observerbeing one of them: written for this use-case exactly, utilizes native Proxies, provides deep-tree observation etc.

我建议选择一些通过代理进行观察的库。有一些,对象观察者就是其中之一:正是为此用例编写的,利用本地代理,提供深度树观察等。

回答by Nirus

@Dan Princesolution should be the first choice always.

@Dan Prince解决方案应该始终是首选

Just in case for some reason if you want to support browsers that are quite older, i would suggest you to go for any polyfill libraries available on Github or use Object.definePropertiesAPIwhich is supported in IE 9 to emulate the same.

出于某种原因,如果您想支持较旧的浏览器,我建议您使用 Github 上可用的任何 polyfill 库或使用IE 9 中支持的Object.definePropertiesAPI来模拟相同的浏览器。

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

Note:This is not a scalable solution. Make an educated decision whether to use the above API for larger data objects and computation intensive requirements.

注意:这不是可扩展的解决方案。对是否将上述 API 用于更大的数据对象和计算密集型需求做出明智的决定。