观察ES6 Maps和Sets的变化

5
有没有办法观察ES6 Maps和Sets的新增和删除?Object.observe不起作用,因为它只适用于被观察对象的直接属性。理论上可以观察到size属性,但无法提供确切的更改信息。另一个想法是替换对象的setget函数与代理版本。是否有更好的方法?如果没有,我很惊讶在编写ES6提案时没有人想到这一点。

1
代理是你唯一的选择。 - Felix Kling
1
子类化它们并覆盖 set/get - Bergi
1
@user5321531:"Object.observe不起作用,因为它只适用于被观察对象的直接属性。" - Felix Kling
@FelixKling 好的,谢谢你的意见。 - Nathan Ridley
2个回答

4
不,使用普通的Map/Set无法实现此功能。仅观察对象属性本身就具有争议性(这就是为什么Object.observe只是一个提案,而不是规范的一部分)。观察私有状态,例如Map或Set的内部(或者Date或Promise等),绝对不在讨论范围之内。
此外,请注意,由于size是一个getter而不是数据属性,Object.observe不会通知您其更改。
正如您提到的那样,您可以通过变异器和观察器之间的协作来实现这种“观察”。您可以使用普通的Map/Set加上一个侧通道(例如返回一个{ Map,EventEmitter }对象的函数),或者通过专门为此目的量身定制的子类或特定实例来实现。

这就是为什么代理应该支持Map和Set,而不仅仅是对象和函数的原因。 - wintercounter

2

目前无法对Set/Map进行子类化。那么这个方法怎么样(只是一个草率的例子)?

//ECMAScript 2015
class XMap
{
  constructor(iterable, observer = null)
  {
    this._map      = new Map(iterable);
    this._observer = observer;
    this._changes  = {};
  }
  set(key, value)
  {
    this._changes.prev = this._map.get(key);
    this._changes.new  = value;
    this._map.set(key, value);

    if(this._observer !== null)
    {
      this._observer(this._changes);
    }
  }
  get(key)
  {
    return this._map.get(key); 
  }
}

var m = new XMap([[0, 1]], changes => console.log(changes));

m.set(0,5);  // console: Object {prev: 1, new: 5}
m.set(0,15); // console: Object {prev: 5, new: 15}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接