This blog post describes the proposed ECMAScript feature “call constructor” (stage 1).
In ECMAScript 6, classes can’t be function-called:
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
let p1 = new Point(1, 2); // OK
let p2 = Point(3, 4); // TypeError
For ES6, there was no categorical objection to classes being function-called. The error was only thrown so that handling function calls via classes could be added later.
If you want to implement a constructor Point
that can be both function-called and constructor-called, you have no choice but to use a constructor function in ES6:
function Point(x, y) {
if (!new.target) {
// Point was function-called
return new Point(x, y);
}
this.x = x;
this.y = y;
}
let p1 = new Point(1, 2); // OK
let p2 = Point(3, 4); // OK
The proposal is about allowing classes to handle function calls via the pseudo-method call constructor()
:
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
call constructor(x, y) {
return new Point(x, y);
}
}
let p1 = new Point(1, 2); // OK
let p2 = Point(3, 4); // OK
Things of note:
super()
call is a compile-time error inside a call constructor (just like it is in normal methods). That is done to keep options open w.r.t. enabling super()
in call constructors in the future.In a future version of the proposal, two meta-properties will probably be added:
class.current
refers to the current class (a function).class.extends
refers to the super-class of the current class.class.current
will help with forwarding from the call constructor to the constructor:
class Foo {
constructor(···) {
···
}
call constructor(...args) {
return new class.current(...args);
}
}
Another possibility is a class decorator that enables function-calling by forwarding from the call constructor to the constructor. For example:
@callConstructor
class Foo {
constructor(···) {
···
}
}
Internally, this class looks like the previous example.