Use hashes as keys instead of toString() for values like object, function to index objects

# Tadas Lapė (5 years ago)

The problem

Javascript allows to index objects not only with strings, numbers, but also with objects. It uses toString() object method to calculate the object index. If method is not overwritten, the generated index is "[object Object]". Many users do not know this or forget this and cause different objects going into same index when using more of them.

The solution

Instead of using the default value "[object Object]" for objects, use their hash codes. You can also prepend them with "function:" or "object:" to let the user know index origin when iterating over object keys. And if person has overwritten the behavior of toString() object method, use it's returned value as index (to consider). This should be less error-prone.

# Michał Wadas (5 years ago)

I wish for "development mode" in browsers, with runtime warning of such code constructs, but that would break backward compatibility.

# Jordan Harband (5 years ago)

By default, the behavior would have to remain the same, or else it would break the web.

See esdiscuss.org/topic/object-id-hash-etc for more on hash codes.

# Michael Luder-Rosefield (5 years ago)

I'd suggest that the best way of doing this, without breaking existing code, is to put some sugar around Maps so that they can be used in a more Object-y way. For starters, Map literal declarations and assignment could benefit from this.

Suggestions for syntax welcome!

# J Decker (5 years ago)
# Michael Luder-Rosefield (5 years ago)

Why not both?

My point is that Map/WeakMap do a lot of what people historically use Object for, but in a better way; certainly, they solve Tadas's issue here.

The trouble is that Objects have a lot of convenient sugar around them that make them easier, and more pleasant, to use. We really shouldn't be in a position where people choose the worse option simply out of sugar.


Dammit babies, you've got to be kind.

# Steve Fink (5 years ago)

On 9/8/19 1:24 PM, Michael Luder-Rosefield wrote:

I'd suggest that the best way of doing this, without breaking existing code, is to put some sugar around Maps so that they can be used in a more Object-y way. For starters, Map literal declarations and assignment could benefit from this.

+1

Not to mention, there is no guarantee that a persistent ID exists. Engines have to keep an object usable as a Map key even if its address changes (eg by a generational GC's minor/nursery collection), but there are ways to do that without associating a permanent numeric ID with the objects. Spidermonkey, in particular, used to rekey its internal hashtables when objects moved in memory (essentially removing the old address and re-inserting with the new, though in practice it was trickier than that because we needed to prevent it from resizing the table awkward time). It no longer does, and indeed now any object you use as a Map key will be lazily given a unique numeric ID, but the point is that implementing this in arbitrary engines is not necessarily as straightforward or free as it might seem. (Though the security argument is an even stronger counterargument.)