This proposal has progressed to the Draft ECMAScript 6 Specification, which is available for review here: specification_drafts. Any new issues relating to them should be filed as bugs at http://bugs.ecmascript.org
This proposal is based on an es-discuss proposal by Russell Leggett. It is essentially a simplification of Dave Herman’s minimal classes proposal. It focuses on providing an absolutely minimal class declaration syntax that all interested parties may be able to easily agree upon.
The text of this proposal was prepared by AllenWB and is derived from Dave Herman’s proposal
Max-min class semantics summarizes decision made at the July 26, TC-39 meeting.
Russell started this by saying:
Is it possible that we can come up with a class syntax that we can all agree is better than nothing, and importantly, leaves possibilities open for future enhancement?
I would propose that the absolute minimal requirements would be:
The following are the same examples used in minimal classes with slight modifications to conform to this proposal. The three.js SkinnedMesh example cited in classes.
class SkinnedMesh extends THREE.Mesh { constructor(geometry, materials) { super(geometry, materials); this.identityMatrix = new THREE.Matrix4(); this.bones = []; this.boneMatrices = []; ... } update(camera) { ... super.update(); } }
The Monster example from classes. Classes do not provide any kind of special private record; private is simply achieved via private name objects.
// a private name used by the Monster class const pHealth = Name.create(); class Monster { // A method named "constructor" defines the class’s constructor function. constructor(name, health) { this.name = name; this[pHealth] = health; } // An identifier followed by an argument list and body defines a // method. A “method” here is simply a function property on some // object. attack(target) { log('The monster attacks ' + target); } // The contextual keyword "get" followed by an identifier and // a curly body defines a getter in the same way that "get" // defines one in an object literal. get isAlive() { return this[pHealth] > 0; } // Likewise, "set" can be used to define setters. set health(value) { if (value < 0) { throw new Error('Health must be non-negative.') } this[pHealth] = value } } // The only way to create prototype data properties is by // modifying the prototype outside of the declaration. Monster.prototype.numAttacks = 0; // Immutable properties can be added with defineProperty. Object.defineProperty(Monster.prototype, "attackMessage", { value: 'The monster hits you!' });
If class properties, including methods, are needed they must also be added outside of the class declaration:
Monster.allMonsters = []; Object.defineMethod(Monster,"numMonsters", function() { return this.allMonsters.length; }
Declaration :
ClassDeclaration
...
ClassDeclaration :
class Identifier ClassHeritage? { ClassBody }
MemberExpression :
ClassExpression
...
ClassExpression :
class Identifier? ClassHeritage? { ClassBody }
ClassHeritage :
extends AssignmentExpression
ExpressionStatement :
[lookahead ∉ { "{", "function", "class" }] Expression ;
// "..." means existing members defined elsewhere
CodeBody :
ClassElement*
ClassElement :
PrototypePropertyDefinition
; //semicolons are allowed but have no significance
PrototypePropertyDefinition :
PropertyName ( FormalParameterList? ) { FunctionBody } // method
*PropertyName ( FormalParameterList? ) { FunctionBody } // generator method
get PropertyName ( ) { FunctionBody } // getter
set PropertyName ( PropertySetParameterList ) { FunctionBody } // setter
Per the May 4 specification draft, the { FunctionBody } sequences above should be replaced by ConciseBody.
The ; empty-element alternative is slightly wrong in my view. With ConciseBody allowing an AssignmentExpression with lookahead restriction, the need for ; is stronger, but only for that case, not for the { FunctionBody } alternative.
Specifically, because of the *PropertyName generator method form, a ; is required after a preceding ConciseBody that is a restricted AssignmentExpression. The alternative is a LineTerminator sensitivity a la ASI.
I suggest we pin down the exact grammar and require ; only after the AssignmentExpression variant of ConciseBody. This problem will arise in ObjectLiteral too.
— Brendan Eich 2012/05/22 21:58
See semantic decisions (PDF) made at July 26, 2012 TC39 meeting
The semantics of minimal classes is described here via desugaring. I’ll use special variables of the form %x for fresh variables not exposed to user code. But desugarings of the contents of a class body can refer to these names bound by their containing class’s desugaring.
A class expression:
(class C { CE ... // where no CE has the PropertyName "constructor" })
is equivalent to:
(do { let %d = function C () { }; for each CE, process it as if it was a PropertyAssignment in an object literal and insert that property into %d.prototype; %d })
A class expression:
(class C { CE ... constructor(cargs) { cbody } CE ... })
is equivalent to:
(do { let %d = function C (cargs) { cbody }; for each CE, process it as if it was a PropertyAssignment in an object literal and insert that property into %d.prototype; %d })
A class expression:
(class C extends D { CE ... constructor(cargs) { cbody } CE ... })
is equivalent to:
(do { let %d = D <| function C (cargs) { cbody }; for each CE, process it as if it was a PropertyAssignment in an object literal and insert that property into %d.prototype; %d })
A class declaration:
class C extends D { CE ... constructor(cargs) { cbody } CE ... })
is equivalent to:
const C = class C extends D { CE ... constructor(cargs) { cbody } CE ... })
%S <| function(cargs) {cbody}(class extends foo () {}) is equivalent to (foo <| function () {})super(/*arguments*/) at some point within the constructor body.The is intended as a closed-ended proposal and is not open for major feature additions.
Future editions of ECMAScript may and probably will extend the proposed class definitions. However, the intent for “ES6” is to only include the features described in this proposal. Attempting to extend this proposal is likely to result in dead-lock that would result in the inclusion of no class definition support in “ES6”.