This is one of several related Object Initialiser Extensions.
Enhance object initialisers provide a self contained declarative construct for defining discrete objects. Such declarations define abstractions that usually need to be named. One way to name an object literal based abstraction is to wrap it in a factory function that is used to create instances of the abstraction. However, that pattern has the disadvantage it requires two distinct constructs to represent the named abstraction and the name is most closely associated with the factory function rather than the object abstraction. This problem can be solved by creating a new declaration form that builds upon object literal syntax:
constructor Point(x,y) { [parent: AbstractPoint] {function isPoint(p) {return p instanceof Point}} //public properties const x:x, const y:y, method plus(delta) { if (isPoint(delta)) return new Point(this.x+delta.x,this.y+delta.y var d = Number(delta): return new Point(this.x+d,this.y+d); } }
Usage example:
var p1 = new Point(0,0); var p2 = new Point(a,b); var p3 = p1.plus(p2).plus(1)
The “body” of a constructor declaration is an extended object literal rather than a function body. It creates a name binding in the current declaration environment whose value is an object that can be invoked as a constructor in a new expression. The object has a [[Construct]] internal property but it does not have a [[Call]] internal method so it cannot be invoked by a CallExpression. The formal parameters correspond to the arguments to the new expression and are in the lexical scope of the extended object literal.
When the constructor object is invoked by a NewExpression it returns a newly created object as specified by the extended object literal that is the constructor body. In addition to the properties defined by the object literal, the new object has an automatically generated constructor property whose value is the constructor object. (If the object literal explicitly defined a constructor property one is not automatically generated). The constructor object does not have a prototype property but instead also has a special [[HasInstance]] internal method that compares the subject object’s constructor property value to the identity of the actual constructor object.
ConstructorDeclaration :
constructor Identifier ( FormalParameterListopt ) ObjectLiteral
The above syntax approximately (additional error check is probably needed) desugars into:
var Identifier = (function (){ var __ctor__ = function (FormalParameterListopt ) { var __obj__ = ObjectLiteral; if (Object.getOwnPropertyDescriptor(__obj__,'constructor') return __obj__; Object.defineProperty(__obj__,'constructor', {value: __ctor__, writable: true, enumerable: false, configurable: true}); return __obj__; }; // runtime.setSpecialConstructorHasInstance(__ctor__); return __ctor__; })();
The [[HasInstance]] internally if implemented in ECMAScript would be:
function [[HasInstance]] (v){ if (typeof v !== 'object' || v===null) return false; if (v.constructor===this) return true; return false; }
class could be used as the keyword for the declaration instead of constructor.