15.3 类的细节
我们到目前为止看到的是类的概要。如果对类的背后原理感兴趣,那就继续阅读下去。让我们以类的语法开始,下面是一个来自于《 Sect. A.4 of the ECMAScript 6 specification 》的经过稍微修改的版本。
ClassDeclaration:
    "class" BindingIdentifier ClassTail
ClassExpression:
    "class" BindingIdentifier? ClassTail
ClassTail:
    ClassHeritage? "{" ClassBody? "}"
ClassHeritage:
    "extends" AssignmentExpression
ClassBody:
    ClassElement+
ClassElement:
    MethodDefinition
    "static" MethodDefinition
    ";"
MethodDefinition:
    PropName "(" FormalParams ")" "{" FuncBody "}"
    "*" PropName "(" FormalParams ")" "{" GeneratorBody "}"
    "get" PropName "(" ")" "{" FuncBody "}"
    "set" PropName "(" PropSetParams ")" "{" FuncBody "}"
PropertyName:
    LiteralPropertyName
    ComputedPropertyName
LiteralPropertyName:
    IdentifierName  /* foo */
    StringLiteral   /* "foo" */
    NumericLiteral  /* 123.45, 0xFF */
ComputedPropertyName:
    "[" Expression "]"
观察之后,得出两个结论:
- 被继承的值可以产生于任何表达式,这意味着可以写出如下的代码:
 
class Foo extends combine(MyMixin, MySuperClass) {}
- 允许方法之间有分号。
 
15.3.1 各种检查
- 错误检查:类名不能是 
eval或arguments;类元素名字不允许重复;名字constructor只能作为普通的方法名,不能用作 getter 、 setter 或者生成器方法。 - 类不能像函数一样调用。如果像函数一样调用,则会抛出 
TypeException异常。 - 原型方法不能用作构造器:
 
class C {
    m() {}
}
new C.prototype.m(); // TypeError
15.3.2 属性的特性( Attributes of properties )
Class declarations create (mutable) let bindings. 对于一个给定的类 Foo :
- 静态的方法 
Foo.*是可写的和可配置的,但不可枚举。使它们可写就允许动态赋值。 一个构造器和它的属性
prototype对象有一个不变的连接:Foo.prototype是不可写的,不可枚举的,不可配置的。Foo.prototype.constructor是不可写的,不可枚举的,不可配置的。
原型方法
Foo.prototype.*是可写的和可配置的,但是不可枚举。
注意在对象字面量中的方法定义会产生可枚举的属性。