using Private name objects for declarative property definition.

Brendan Eich brendan at mozilla.com
Sat Jul 9 08:48:44 PDT 2011


On Jul 9, 2011, at 12:48 AM, Andreas Rossberg wrote:

> On 9 July 2011 00:24, Brendan Eich <brendan at mozilla.com> wrote:
>> On Jul 8, 2011, at 2:43 PM, Andreas Rossberg wrote:
>>> One minor suggestion I'd have is to treat names as a proper new
>>> primitive type, i.e. typeof key == "name", not "object". That way, it
>>> can be defined much more cleanly what a name is, where its use is
>>> legal (as opposed to proper objects), and where it maybe enjoys
>>> special treatment.
>> 
>> We went back and forth on this. I believe the rationale is in the wiki (but
>> perhaps in one of the strawman:*name* pages). There are a couple of reasons:
>> 1. We want private name objects to be usable as keys in WeakMaps. Clearly we
>> could extend WeakMaps to have either "object" (but not "null") or "name"
>> typeof-type keys, but that complexity is not warranted yet.
> 
> I can see that being a relevant use case for weak maps. But the same
> logic applies to using, say, strings or numbers as keys. So isn't the
> right fix rather to allow weak maps to be keyed on any JS value?

Sam covered this, but just to emphasize: only object has unique identity due to its reference-type nature. Adding names as a distinct reference and typeof type, extending WeakMap to have as its key type (object | name), adds complexity compared to subsuming name under object.


>> 2. Private name objects are deeply frozen and behave like value types (since
>> they have no copy semantics and you can only generate fresh ones). Thus they
>> are typeof-type "object" but clearly distinct from string-equated property
>> names that JS has sported so far.
> 
>> Oh, of course you meant to distinguish private names via typeof precisely to tell that they are not converted to strings when used as property names. For that test, the proposal
>> 
>> http://wiki.ecmascript.org/doku.php?id=harmony:private_name_objects
>> 
>> proposes an isName predicate function exported from the "@name" built-in module.
> 
> Yes, I know. But this is introducing a kind of ad-hoc shadow type
> mechanism.

We have many such, and JS authors develop their own. ES5 added Array.isArray to help with a common "is this object, which may have come from a different Array built-in in a different global object (window or iframe)" question.

Given object as a wide type, such ad-hoc type mechanisms are inevitable. Original JS had .constructor testing. ES3 added instanceof, which missed the mark due to multiple globals. There's nothing new or wrong in adding something like isName, IMHO -- esp. compared with the alternative of a new typeof type, WeakMap key type, and possibly other wrinkles we haven't thought of yet.


> Morally, this is a type distinction, so why not make it
> one?

Sorry, typeof is not the only or best way to make such distinctions. It's for testing among different primitive value types (including null in ES.next, yay) vs. the one reference type object.


> Moreover, I feel that ES already has too many classification
> mechanisms (typeof, class, instanceof), so adding yet another one
> through the back door doesn't seem optimal.

See above, there is nothing novel or evil in isName or isArray (another example) isGenerator.

typeof is for non-object primitive type classification, vs. object. It's extensible but not to be extended lightly.

instanceof is for proto-chain walking to find a constructor.prototype, and a bit of an attractive nuisance in the world of multiple global objects (browser windows/frames).

I'm not sure which "class" you mean. The [[ClassName]] disclosed by Object.prototype.toString.call(x).slice(8,-1) is one possibility, which is one of the many and user-extensible ways of distinguishing among objects. ES.next class is just sugar for constructor/prototype patterns with crucial help for extends and super.

There is a two-level hierarchy here. Some of the object-specific stuff did not pan out as hoped (instanceof in particular). Sorry I didn't head that off, my ES3 time on committee was limited.


> 
>> [...] in the case of private name objects, we don't think we have
>> good enough reason to add a typeof name -- and then to complicate WeakMap.
> 
> Why do you think that it would that make WeakMap more complicated? As
> far as I can see, implementations will internally make that very type
> distinction anyways.

No, as proposed private name objects are just objects, and WeakMap implementations do not have to distinguish (apart from usual GC mark method virtualization internal to implementations) between names and other objects used as keys.


> And the spec also has to make it, one way or the
> other.

Not if names are objects.


> I don't think that the more general form would be a big deal for
> implementations. And it is still easy to identify object expressions
> with static shape syntactically: they don't use [_]. Analyses
> shouldn't be harder than for a series of assignments (which you
> probably could desugar this into).

Yes, [propname] is all plausible as an extension in object literals. I have mixed feelings about it, but it has come up, as I noted in a recent message, from users wanting to intermix a little property name computation in a mostly-static-shape literal.


>> Here, with obj = { [expr]: value } as the way to compute a property name in
>> an object initialiser (I must not write "object literal" any longer), we are
>> proceeding up another small and separate hill. But, is this the right design
>> for object initialisers (which the normative grammar does call
>> "ObjectLiterals")?
> 
> (If you care about that, then that's a misnomer already, since the
> property values have always been arbitrary expressions.)

Yup. The nonterminal name, used colloquially  as well, is the least of our worries, so forget I mentioned it!

/be


More information about the es-discuss mailing list