Reputation: 34396
Is there any way to observe additions to and removals from ES6 Maps and Sets? Object.observe doesn't work because it is only applies to direct properties of the observed object. Hypothetically the size
property could be observed, but no indication would be provided of exactly what has changed. Another idea would be to replace the object's set
and get
functions with proxified versions. Is there a better way? If not, I'm surprised that nobody thought of this when the proposals were being written for ES6.
Upvotes: 5
Views: 944
Reputation: 1265
Subclassing for Set/Map
is not working at the moment. How about this method (just hasty example)?
//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}
Upvotes: 2
Reputation: 112827
No, there is no way to do this with a vanilla Map/Set. In general observation of object properties alone is controversial (that is why Object.observe
is only a proposal, and not an accepted part of the spec). Observing private state, like the internals of a Map or Set (or Date or Promise, for that matter), is definitely not on the table.
Note also that since size
is a getter, not a data property, Object.observe
will not notify you of changes to it.
As you mention, you can achieve such "observation" via collaboration between the mutator and the observer. You could either do this with a normal Map/Set plus a side-channel (e.g. a function returning a { Map, EventEmitter }
object), or via a subclass tailored for the purpose, or a specific instance created for that purpose.
Upvotes: 4