Reputation: 45
I have an object:
var myObject = {myKey: myVal};
I would like to ascribe some metadata to this object, without editing the object directly. For example, let's say I want to add a tag, "myTag," to that object. One way I could do this by creating a new object that matches tags to a list of objects:
var tags = {
'myTag': [myObject, someOtherObject, ...],
'myTag2': [otherObject, myObject, ...]
}
The problem is if I come across another reference to that object and want to know its existing tags are, I have to iterate over the whole tag list and see if there is a reference to that object in each array. This will become prohibitively expensive as the lists of tags and objects references grow.
I've been looking for some way to "hash" object references, such that I could flip the tags list on it's head, like so:
var tags = {
myObject: ['myTag', 'myTag2']
}
But since object references can't be used as keys, I cannot find any clean way to accomplish this with performance in mind. Any thoughts on how to approach this problem?
Upvotes: 1
Views: 59
Reputation: 708056
In ES6, you can use a weakMap
which allows an object to be a key. So, you can directly store an object in a map
, weakMap
or a set
without having to modify the object.
In ES5, an object can't be a key, so you will have to add a property to the object that you can use as a handle for the object. You can't do it without editing the object. The property you attach can be made read-only and non-enumerable (so it won't be seen by most code). That's the least impact you can have on the object in ES5.
This technique of adding a known property that has some sort of unique value assigned to it to keep track of a given object is exactly what people did to work around this issue before we had the weakMap in ES6.
This Set polyfill (designed to mimic the ES6 implementation as close as possible but to work in ES5) allows you to add objects to the Set and uses the described work-around. If you examine the getKey()
function in that code, you can see a technique that uses a known property name on the object and then uses a counter and a prefix based on the type of the object to coin a unique identifier for that specific object. That key is then attached to the object in a non-enumerable, non-configurable, non-writable way such that it becomes a unique identifier for the object that is generally only seen by those who know what to look for.
From then on, anyone looking at that object can check the identifier attached to it and compare it to some previous identifier to see if this is indeed the same object. Of, the identifier itself could be stored in some lookup table without creating any unwanted references to this object (since the identifier is just a string).
Upvotes: 1