Jason Orendorff jason.orendorff at gmail.com
Tue Jun 17 12:21:59 PDT 2014

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`

*   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-
"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 ] )"

More information about the es-discuss mailing list