Prototypes as the new class declaration
brendan at mozilla.com
Sat Jun 18 11:38:43 PDT 2011
On Jun 18, 2011, at 10:30 AM, Axel Rauschmayer wrote:
>> Now, we could have a "second protocol" as Irakli's gists show. He wires up both per-instance and "static" (ugh, I mean constructor-side) 'new' methods that bottom out by calling the constructor. This is not quite the second protocol you proposed that we agreed would be less desirable, all else equal, than a single constructor protocol. It's a layering on top, rather than an additional parallel novel protocol.
> Note though that there shouldn’t be too many steps to make this happen.
> I like the image you mentioned (of flipping things around):
> - Current “class”: a constructor containing a prototype
> - New-style class: a prototype containing a constructor
> An interesting question is how much this approach would go against the expectations of existing code (and if it really has to conform %100 to them).
That is the $64,000 question.
> The following measures should make the differences minimal:
> - Object.getPrototypeOf(obj).constructor: should it always point to the constructor? Or is it a reference to a class construct (either old-style or new-style)? Most of the code will probably only use it as the operand of the "new" operator.
I'm not sure what you mean here. The 'constructor' property of prototype objects is writable, but overwriting it could be a useful technique. It's unlikely to be accidentally clobbered, but user-defined and unfrozen function objects can have their .prototype properties overwritten too, so there' s no greater integrity problem in relying on .constructor compared to .prototype for user-defined functions.
> - o instanceof C: treat non-function operands differently. Then simply desugars to C.isPrototypeOf(o).
The details matter. Currently instanceof layers on spec-internal [[HasInstance]], implemented in the spec only by Function objects. We could add [[HasInstance]] for all objects that does as you say: tests this.isPrototypeOf(o) for argument o (the left operand of instanceof; |this| refers to the right operand). But do we want to add [[HasInstance]] for all objects?
Or we could check for Y.constructor (object-detect it, as it were) in the x instanceof Y semantics, and use that property's value instead of Y as |this| when calling [[HasInstance]]. This is less efficient and at the limit less reliable given the writability of .constructor.
> - new C(): treat non-function operands differently. After construction, things have to look similar to what they look like today. I don’t think it necessarily matters how to get there.
Details always matter. Right now new Y() delegates to Y.[[Construct]] -- but given proxies and other precedents, I think we do not want all objects to grow a [[Construct]] internal method. Compare to [[HasInstance]] above: I believe that is more plausible as a universal internal method.
So we could elaborate the 11.2.2 "The new Operator" semantics to object-detect .constructor. Again some efficiency concerns but modern JITs can optimize; also the reliance on writable .constructor.
More information about the es-discuss