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 各种检查

  • 错误检查:类名不能是 evalarguments ;类元素名字不允许重复;名字 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.* 是可写的和可配置的,但是不可枚举。

注意在对象字面量中的方法定义会产生可枚举的属性。

results matching ""

    No results matching ""