Overriding Map/etc with get/set hooks?

Tab Atkins Jr. jackalmage at gmail.com
Tue May 21 10:42:38 PDT 2013


On Tue, May 21, 2013 at 4:19 AM, Brendan Eich <brendan at mozilla.com> wrote:
> David Bruant wrote:
>> This description ("arbitrary string keys", "bidirectional link with style
>> rule") suggests that you want a proxy (canonical values are in the style
>> rule, the proxy is just a façade with a bit of validation/coercion logic).
>> That's the sort of use case they've been introduced for.
>
> I don't see why a proxy is required if the API is get/set/has (like Map's).
> We're not making properties appear without knowing their names, so this is
> not a proxy use-case on its face.
>
> Of course, coercing key type makes the API not Map. So if the
> bi-directionality is important, this would be a custom Map-like class.
>
> So Tab: why do you want to abuse Map instead of make a custom class?

Restating from my earlier post:

1. when someone asks "is this Map-like?" in an appropriately idiomatic
JS way, they get a "yes" answer.
2. when someone adds a new function to Maps in an appropriately
idiomatic JS way, the method also applies to this object
3. when JS expands the set of built-in methods for Map, it also gets
applied to this object without me having to update my spec
4. for all the existing Map methods, I get identical/equivalent methods
without having to manually redefine every single one of them

All of these follow from the basic statement that *this is a map*,
because it clearly is.  It's limited to string keys and values, but
that's just some coercion rules.  Every single operation defined on
Maps currently is meaningful and useful for this object, and virtually
any method you can imagine adding to Maps in the future is also
meaningful and useful.

Ducktyping this as a Map is terrible, because it breaks #2/3/4, and
arguably #1 depending on what you consider an "appropriately
idiomatic" way of asking if something is Map-like.

Just subclassing Maps and providing my own get/set functions is not as
terrible, but still bad for a few reasons: I need to study the ES spec
very carefully to figure out which operations are "basic" (interact
directly with [[MapData]] rather than going through existing
operations) and redefine all of them, and anyone who ever does
something like Map.prototype.set.call(myObj, ...) will break the
invariants I need maintained, with mysterious and undefined results.

This should be super-simple - I just want to supply a custom object as
the [[MapData]] which can intercept sets so it can coerce the values
beforehand.  In every other way, this is a Map.

~TJ


More information about the es-discuss mailing list