ECMAScript proposal: function-callable classes
This blog post describes the proposed ECMAScript feature “call constructor” (stage 1).
Classes can’t be function-called in ES6
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.
Function-callable constructors in ES6
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
Function-callable classes via the proposed call constructor
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:
- A call constructor is not inherited by subclasses, you have to put it into each class you want to function-call.
- A
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. enablingsuper()
in call constructors in the future.
Possible future additions to the proposal
New meta-properties
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);
}
}
A decorator for making classes function-callable
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.
Further reading
- “Call constructor proposal” by Yehuda Katz and Allen Wirfs-Brock
- Chapter “Classes” in “Exploring ES6”
Comments
Post a Comment