@@new

Erik Arvidsson erik.arvidsson at gmail.com
Tue Jun 17 12:55:09 PDT 2014


Remember that

```js
class C {
  constructor() {}
}
assert(C === C.prototype.constructor);
```

What would `C.prototype.constructor` look like with your proposal? Is `C
=== C[@@new]`?

On Tue Jun 17 2014 at 3:22:05 PM, Jason Orendorff <jason.orendorff at gmail.com>
wrote:

> Allen asked me to fill out what @@new would mean. Here it is.
>
>
> ## How `new X` works
>
> `new X(...args)` ==== `X[@@new](...args)`
>
>
> ## How it works for ES5 builtin constructors
>
> `Number(value)` is specified in one section.
>
> `Number[@@new](value)` is specified in another section.
>
> To support subclassing, `Number[@@new]()`, unlike ES5 [1], would set the
> new object's prototype to `this.prototype` rather than `Number.prototype`.
> Otherwise it all works just like ES5.
>
> The same goes for Object, Array, Function, Date, and the other builtins.
>
>
> ## How it works for regular functions
>
> `Function.prototype[@@new](...arguments)` is called. It works like this:
>
> 1.  Let proto = `this.[[Get]]("prototype", this)`.
>
> 2.  If proto is not an object, throw a TypeError.
>
> 3.  Let obj = ObjectCreate(proto).
>
> 4.  If the this value or any object on its prototype chain is an ECMAScript
>     language function (not a class), then
>
>     a.  Let F be that object.
>
>     b.  Let result = `F.[[Call]](obj, arguments)`.
>
>     c.  If Type(result) is Object then return result.
>
> 5.  Return obj.
>
> For regular functions, this behaves exactly like the `[[Construct]]`
> internal
> method in ES5 [2]. Step 4 is there to support regular functions and ES6
> classes
> that subclass regular functions.
>
>
> ## How it works for ES6 classes
>
> The special `constructor` method in ClassDeclaration/ClassExpression
> syntax
> would desugar to a static @@new method. This class:
>
>     class Point {
>         constructor(x = 0, y = 0) {
>             this.x = x;
>             this.y = y;
>         }
>     }
>
> would amount to this:
>
>     class Point {
>         static [Symbol.new](x = 0, y = 0) {
>             var obj = super[Symbol.new]();
>             obj.x = x;
>             obj.y = y;
>             return obj;
>         }
>     }
>
> As in the current drafts, ES6 would have to do something mildly fancy (see
> [3]
> and step 8 of [4]) to perform the desugaring.
>
> If a class has no `constructor` method, it inherits the base class's static
> @@new method.
>
> The "super Arguments" call syntax in the ES6 drafts would be constrained to
> appear only at the top of a constructor, as in Java:
>
>     class PowerUp {
>         constructor(name, price) { ... }
>     }
>
>     class RocketPack extends PowerUp {
>         constructor() {
>             super("Rocket Pack", 1000);
>             this.fuel = FULL_TANK;
>         }
>     }
>
> The RocketPack constructor would behave like this:
>
>         static [Symbol.new]() {
>             var obj = super[Symbol.new]("Rocket Pack", 1000);
>             obj.fuel = FULL_TANK;
>             return obj;
>         }
>
> This has different runtime semantics compared the `super()` syntax in the
> current ES6 draft, but it serves the same purpose.
>
> And that's all.
>
>
> ## Benefits
>
> *   As with Allen's proposal, we would drop [[Construct]] and the
> `construct`
>     trap.
>
> *   Instances of builtin classes are never exposed to scripts before
>     their internal slots are fully initialized.
>
> *   @@create can be dropped entirely, but we retain the benefit to
> implementers
>     that all Maps (for example) can have the same in-memory layout, and
> other
>     objects can't become Maps at runtime.
>
> *   Base class constructors are always called.
>
> *   The ES6 draft language in [5] step 5, and many other similar places,
> would
>     be backed out. ("If Type(O) is Object and O has a [[NumberData]]
> internal
>     slot and the value of [[NumberData]] is undefined, then...")
>
> *   The current ES6 draft specifies new builtin constructors (Map, Set,
>     WeakMap) to throw a TypeError if called without `new`. This new
> convention
>     could be reversed to what ES5 does with Function and Array: `Map()`
> would
>     be the same as `new Map()`. User-defined classes could work this way
> too.
>     I think developers would appreciate this.
>
> *   These productions would be dropped from the ES6 grammar:
>
>         MemberExpression : new super Arguments
>         NewExpression : new super
>
>     If for whatever reason users want these, they can call
>     `super[Symbol.new]()`. But I think they will no longer be needed.
>
>     This would reduce the number of `super` forms to these 3:
>
>         super.IdentifierName  // allowed in all methods
>         super[Expression]     // allowed in all methods
>         super(arguments)      // only allowed in constructors
>
>
> [1]: http://people.mozilla.org/~jorendorff/es5.1-final.html#sec-15.7.2.1
> "ES5 new Number ( [ value ] )"
> [2]: http://people.mozilla.org/~jorendorff/es5.1-final.html#sec-13.2.2
> "ES5 [[Construct]]"
> [3]: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-
> static-semantics-constructormethod
> "ES6 Static Semantics: ConstructorMethod"
> [4]: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-
> runtime-semantics-classdefinitionevaluation
> "ES6 Runtime Semantics: ClassDefinitionEvaluation"
> [5]: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-
> number-constructor-number-value
> "ES6 Number ( [ value ] )"
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20140617/b9174755/attachment.html>


More information about the es-discuss mailing list