@@new
Domenic Denicola
domenic at domenicdenicola.com
Wed Jun 18 06:55:52 PDT 2014
What happens if I put [Symbol.new] on a non-function object? Is it now constructable? Presumably still not callable though, right?
________________________________
From: Jason Orendorff<mailto:jason.orendorff at gmail.com>
Sent: 2014-06-17 15:22
To: Allen Wirfs-Brock<mailto:allen at wirfs-brock.com>
Cc: EcmaScript<mailto:es-discuss at mozilla.org>; Mark Miller<mailto:erights at gmail.com>
Subject: @@new
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/20140618/7d6c63af/attachment.html>
More information about the es-discuss
mailing list