[TypeScript] 编程实践之1: Google的TypeScript代码风格8:类

TS代码规范 良好的TypeScript 代码规范可以帮助技术团队统一代码风格,提高代码质量和可读性,同时也能避免一些常见的编程错误。 阅读详情

8 类

TypeScript扩展了JavaScript类,以在构造函数中包括类型参数,实现子句,可访问性修饰符,成员变量声明和参数属性声明。

TODO:抽象类。

8.1 类声明

类声明声明了类类型和构造函数。

ClassDeclaration: ( Modified )
	class BindingIdentifieropt TypeParametersopt ClassHeritage { ClassBody }

ClassDeclaration在包含的声明空间中引入了命名类型(类类型)和命名值(构造函数)。类类型由在类主体中声明的实例成员和从基类继承的实例成员形成。构造函数被赋予由构造函数声明,类主体中的静态成员声明以及从基类继承的静态成员形成的匿名类型。构造函数初始化并返回类类型的实例。

类声明的BindingIdentifier可能不是预定义的类型名称之一(第3.8.1节)。仅当类声明出现在导出默认声明中时,BindingIdentifier才是可选的(11.3.4.2节)。

类可以选择具有类型参数(第3.6.1节),这些类型参数用作在类型引用中引用该类时要提供的实际类型的占位符。具有类型参数的类称为泛型类。通用类声明的类型参数在整个声明的范围内,并且可以在ClassHeritage和ClassBody中引用。

下面的示例在包含的声明空间中引入了一个名为’Point’的命名类型(类类型)和一个名为’Point’的命名值(构造函数)。

class Point {  
    constructor(public x: number, public y: number) { }  
    public length() { return Math.sqrt(this.x * this.x + this.y * this.y); }  
    static origin = new Point(0, 0);  
}

命名类型’Point’完全等同于

interface Point {  
    x: number;  
    y: number;  
    length(): number;  
}

命名值“ Point”是一个构造函数,其类型与声明对应

var Point: {  
    new(x: number, y: number): Point;  
    origin: Point;  
};

引用类的上下文区分了类类型和构造函数。 例如,在赋值语句中

var p: Point = new Point(10, 20);

类型注释中的标识符“ Point”是指类类型,而新表达式中的标识符“ Point”是指构造函数对象。

8.1.1 类继承规范

TODO:更新本节,以反映类扩展子句中的表达式。

类的继承规范由可选的extends和implements子句组成。 extend子句指定该类的基类,而Implements子句指定用于验证该类提供了实现的一组接口。

ClassHeritage: ( Modified )
	ClassExtendsClauseopt ImplementsClauseopt

ClassExtendsClause:
	extends  ClassType

ClassType:
	TypeReference

ImplementsClause:
	implements ClassOrInterfaceTypeList

包含extends子句的类称为派生类,而extends子句中指定的类称为派生类的基类。当类继承规范忽略extends子句时,该类没有基类。但是,就像每种对象类型一样,对该类的类型引用(第3.3.1节)似乎具有名为“ Object”的全局接口类型的成员,除非这些成员被名称相同的成员隐藏。类。

类继承规范必须满足以下约束,否则会发生编译时错误:

  • 如果存在,则extends子句中指定的类型引用必须表示一个类类型。此外,当作为表达式求值时,类型引用的TypeName部分必须是对类构造函数的引用。
  • 类声明不能直接或间接指定源自同一声明的基类。换句话说,无论类型参数如何,类都不能直接或间接地成为其自身的基类。
  • 声明的类的this-type(第3.6.3节)必须可分配(第3.11.4节)给基本类型引用以及Implements子句中列出的每个类型引用。
  • 由类声明创建的构造函数类型必须可分配给基类构造函数类型,而忽略构造签名。

以下示例说明了违反上述第一条规则的情况:

class A { a: number; }

namespace Foo {  
    var A = 1;  
    class B extends A { b: string; }  
}

当作为表达式求值时,extends子句中的类型引用“ A”不引用“ A”的类构造函数(而是引用局部变量“ A”)。

唯一违反上述最后两个约束的情况是,当一个类使用不兼容的新成员覆盖一个或多个基类成员时。

请注意,由于TypeScript具有结构化的类型系统,因此类无需明确声明其已实现接口-它足以使该类仅包含适当的实例成员集。 类的Implements子句提供一种机制来断言和验证该类包含适当的实例成员集,但否则对类类型没有影响。

8.1.2 类体

类主体由零个或多个构造函数或成员声明组成。 不允许在类的主体中使用语句-语句必须放在构造函数或成员中。

ClassElement: ( Modified )
	ConstructorDeclaration
	PropertyMemberDeclaration
	IndexMemberDeclaration

类的主体可以选择包含一个构造函数声明。 构造器声明在第8.3节中描述。

成员声明用于声明类的实例和静态成员。 属性成员声明在8.4节中描述,而索引成员声明在8.5节中描述。

8.2 成员

类的成员包括通过类主体中的成员声明引入的成员以及从基类继承的成员。

8.2.1 实例成员和静态成员

成员是实例成员或静态成员。

实例成员是类类型(第8.2.4节)及其关联的this类型的成员。 在构造函数,实例成员函数和实例成员访问器中,此类型是类的this-type(第3.6.3节)。

静态成员使用static修饰符声明,并且是构造函数类型的成员(第8.2.5节)。 在静态成员函数和静态成员访问器中,此类型是构造函数的类型。

类类型参数不能在静态成员声明中引用。

8.2.2 可访问性

物业成员具有公共,私人或受保护的访问权限。缺省值为公共可访问性,但是属性成员声明可以包括public,private或protected修饰符,以明确指定所需的可访问性。

公共财产成员可以不受限制地随处访问。

只能在其声明类中访问私有财产成员。具体来说,只能在C的类主体中访问在C类中声明的私有成员M。

受保护的属性成员只能在其声明类和从其声明类派生的类中访问,并且受保护的实例属性成员必须通过封闭类或其子类的实例进行访问。具体来说,只能在C的类主体或从C派生的类的类主体中访问在类C中声明的受保护成员M。此外,当在主体中的属性访问EM中访问受保护实例成员M时对于类D,无论类型参数如何,都要求E的类型为D或直接或间接以D为基本类型的类型。

私有和受保护的可访问性仅在编译时强制执行,仅表示意图。由于JavaScript没有提供在对象上创建私有和受保护的属性的机制,因此无法在运行时在动态代码中强制私有和受保护的修饰符。例如,可以通过将对象的静态类型更改为Any并动态访问成员来破坏私有和受保护的可访问性。

下面的示例演示了私有和受保护的可访问性:

class A {  
    private x: number;  
    protected y: number;  
    static f(a: A, b: B) {  
        a.x = 1;  // Ok  
        b.x = 1;  // Ok  
        a.y = 1;  // Ok  
        b.y = 1;  // Ok  
    }  
}

class B extends A {  
    static f(a: A, b: B) {  
        a.x = 1;  // Error, x only accessible within A  
        b.x = 1;  // Error, x only accessible within A  
        a.y = 1;  // Error, y must be accessed through instance of B  
        b.y = 1;  // Ok  
    }  
}

在类“ A”中,因为在“ A”中声明了“ x”,所以允许对“ x”的访问,并且由于对二者都通过“ A”的实例或从其派生的类型进行,因此允许对“ y”的访问 ‘一个’。 在类“ B”中,不允许访问“ x”,并且第一次访问“ y”是错误的,因为它是通过实例“ A”发生的,该实例不是从封闭类“ B”派生的。

8.2.3 继承和重置

派生类从其未重写的基类继承所有成员。继承意味着派生类隐式包含基类的所有未重写成员。仅公共和受保护的财产成员可以被覆盖。

当派生类的属性成员与基类属性成员具有相同的名称和种类(实例或静态)时,可以说派生类中的属性成员将覆盖基类中的属性成员。覆盖属性成员的类型必须可分配给覆盖属性成员的类型(第3.11.4节),否则会发生编译时错误。

派生类实例成员函数可以覆盖基类实例成员函数,而其他种类的成员则不能。

派生类实例成员变量和访问器可以覆盖基类实例成员变量和访问器,而其他种类的成员则不能。

如上所述,只要类型兼容,基类静态属性成员就可以被任何类型的派生类静态属性成员覆盖。

当派生类索引成员与基类索引成员具有相同的索引类型(字符串或数字)时,可以说派生类中的索引成员将覆盖基类中的索引成员。覆盖索引成员的类型必须可分配给覆盖索引成员的类型(第3.11.4节),否则会发生编译时错误。

8.2.4 class类型

类声明声明了一个名为类类型的新命名类型(第3.7节)。 在类的构造函数和实例成员函数中,此类型是该类类型的this-type(第3.6.3节)。 类类型具有以下成员:

  • 类主体中每个实例成员变量声明的属性。
  • 类主体中每个实例成员函数声明的函数类型属性。
  • 类主体中每个唯一命名的实例成员访问器声明的属性。
  • 使用public,private或protected修饰符声明的每个构造函数参数的属性。
  • 类主体中每个实例索引成员声明的索引签名。
  • 所有未在类中重写的基类实例属性或索引成员。

一个类的所有实例属性成员(包括私有或受保护的那些实例属性成员)必须满足3.9.4节中指定的该类的索引成员所隐含的约束。

在这个例子中

class A {  
    public x: number;  
    public f() { }  
    public g(a: any) { return undefined; }  
    static s: string;  
}

class B extends A {  
    public y: number;  
    public g(b: boolean) { return false; }  
}

“ A”的类类型等效于

interface A {  
    x: number;  
    f: () => void;  
    g: (a: any) => any;  
}

并且“ B”的类类型等效于

interface B {  
    x: number;  
    y: number;  
    f: () => void;  
    g: (b: boolean) => boolean;  
}

请注意,类中的静态声明不会影响类的类型,相反,静态声明会在构造函数对象上引入属性。 还要注意,在“ B”中声明“ g”会覆盖从“ A”继承的成员。

8.2.5 构造函数类型

由类声明引入的构造函数的类型称为构造函数类型。构造函数的类型具有以下成员:

  • 如果该类不包含构造函数声明且没有基类,则为不带参数的单个构造签名,该签名具有与该类相同的类型参数(如果有),并返回带有作为类型实参传递的那些类型参数的类类型的实例化。
  • 如果该类不包含构造函数声明并且具有基类,则在将类型参数替换为基类类型引用中指定的类型参数之后,一组构造签名与基类构造函数类型具有相同的参数。与类(如果有)相同的类型参数,并返回具有作为类型实参传递的那些类型参数的类类型的实例化。
  • 如果类包含没有重载的构造函数声明,则为带有构造函数实现的参数列表的构造签名,该签名具有与类相同的类型参数(如果有),并返回带有作为类型传递的那些类型参数的类类型的实例化论点。
  • 如果该类包含带有重载的构造函数声明,则包含带有重载的参数列表的一组构造签名,这些签名均具有与该类相同的类型参数(如果有),并返回带有通过以下方式传递的那些类型参数的类类型的实例化输入参数。
  • 类主体中每个静态成员变量声明的属性。
  • 类主体中每个静态成员函数声明的函数类型属性。
  • 类主体中每个唯一命名的静态成员访问器声明的属性。
  • 一个名为“ prototype”的属性,该属性的类型是类类型的实例化,其中为每个类型参数提供类型Any。
  • 所有未在类中重写的基类构造函数的类型属性。

每个类自动包含一个名为“ prototype”的静态属性成员,该成员的类型为包含类型的Any类,该类替换每个type参数。

这个例子

class Pair<T1, T2> {  
    constructor(public item1: T1, public item2: T2) { }  
}

class TwoArrays<T> extends Pair<T[], T[]> { }

引入两个对应于

interface Pair<T1, T2> {  
    item1: T1;  
    item2: T2;  
}

interface TwoArrays<T> {  
    item1: T[];  
    item2: T[];  
}

和两个对应的构造函数

var Pair: {  
    new <T1, T2>(item1: T1, item2: T2): Pair<T1, T2>;  
}

var TwoArrays: {  
    new <T>(item1: T[], item2: T[]): TwoArrays<T>;  
}

请注意,构造函数类型中的每个构造签名都具有与其类相同的类型参数,并使用作为类型实参传递的那些类型参数返回其类的实例化。 还要注意,当派生类未声明构造函数时,在将构造签名从基本构造函数类型传播到派生构造函数类型之前,将替换基类引用中的类型参数。

8.3 构造函数声明

构造函数声明声明一个类的构造函数。

ConstructorDeclaration:
	AccessibilityModifieropt constructor ( ParameterListopt ) { FunctionBody }
	AccessibilityModifieropt constructor ( ParameterListopt ) ;

指定主体的构造函数声明称为构造函数实现,而没有主体的构造函数声明称为构造函数重载。可以在一个类中指定多个构造函数重载,但是一个类最多可以具有一个构造函数实现。类中的所有构造函数声明必须指定相同的修饰符集。仅支持公共构造函数,而私有或受保护的构造函数会导致错误。

在没有构造函数声明的类中,提供了一个自动构造函数,如第8.3.3节所述。

当类具有构造函数重载时,重载确定提供给构造函数对象的类型的构造签名,并且构造函数实现签名(如果有)必须可分配给该类型。否则,构造函数实现本身将确定构造签名。这与函数声明中处理重载的方式完全相同(第6.2节)。

当一个类同时具有构造函数重载和构造函数实现时,重载必须在实现之前,并且所有声明都必须是连续的,并且中间没有语法元素。

允许构造函数的函数体包含return语句。如果return语句指定表达式,则这些表达式必须具有可分配给该类的this-type(第3.6.3节)的类型。

泛型类的类型参数在范围内,可以在构造函数声明中访问。

8.3.1 构造函数参数

与函数类似,只有构造函数实现(而非构造函数重载)才能为可选参数指定默认值表达式。 此类默认值表达式引用它是编译时错误。 当输出目标为ECMAScript 3或5时,对于具有默认值的每个参数,为构造函数生成的JavaScript中将包含一条语句,该语句将默认值替换为省略的参数。

ConstructorImplementation的参数可以带有public,private或protected修饰符作为前缀。 这称为参数属性声明,是用于声明与参数名称相同的属性并使用参数的值对其进行初始化的简写形式。 例如,声明

class Point {  
    constructor(public x: number, public y: number) {  
        // Constructor body  
    }  
}

等价于

class Point {  
    public x: number;  
    public y: number;  
    constructor(x: number, y: number) {  
        this.x = x;  
        this.y = y;  
        // Constructor body  
    }  
}

参数属性声明可以声明一个可选参数(通过添加问号或默认值),但是此类声明引入的属性始终被视为必需属性(第3.3.6节)。

8.3.2 超类调用

超级调用(第4.9.1节)用于调用基类的构造函数。 超级调用由关键字super组成,后跟括号中的参数列表。 例如:

class ColoredPoint extends Point {  
    constructor(x: number, y: number, public color: string) {  
        super(x, y);  
    }  
}

没有extends子句的类的构造函数不能包含超级调用,而派生类的构造函数必须在其函数体内的某个位置至少包含一个超级调用。 不允许在构造函数外部或构造函数内部的局部函数中进行超级调用。

如果满足以下两个条件,则构造函数主体中的第一条语句必须是超级调用:

  • 包含类是派生类。
  • 构造函数声明参数属性,或者包含类声明带有初始化程序的实例成员变量。

在这种必需的超级调用中,参数表达式引用此是编译时错误。

如果该类没有基类,则使用初始化程序对参数属性和实例成员变量进行初始化,如果该类没有基类,则立即进行初始化;如果该类是派生类,则在超级调用之后立即进行初始化。

8.3.3 自动构造函数

如果类省略了构造函数声明,则会提供一个自动构造函数。

在没有extends子句的类中,自动构造函数没有参数,除了执行实例成员变量初始化程序(第8.4.1节)(如果有)外,不执行任何操作。

在派生类中,自动构造函数具有与基类构造函数相同的参数列表(并可能有重载)。 自动提供的构造函数首先使用等效于的调用将调用转发给基类构造函数

BaseClass.apply(this, arguments);

然后执行实例成员变量初始化器(如果有)。

8.4 属性成员函数声明

属性成员声明可以是成员变量声明,成员函数声明或成员访问器声明。

PropertyMemberDeclaration:
	MemberVariableDeclaration
	MemberFunctionDeclaration
	MemberAccessorDeclaration

没有静态修饰符的成员声明称为实例成员声明。实例属性成员声明以类类型(第8.2.4节)声明属性,并且必须指定包含类中所有实例属性成员和参数属性声明中唯一的名称,但实例get和set访问器声明可以成对出现指定相同的名称。

具有静态修饰符的成员声明称为静态成员声明。静态属性成员声明以构造函数类型(第8.2.5节)声明属性,并且必须指定包含类中所有静态属性成员声明中唯一的名称,但static get和set访问器声明可以成对指定。一样的名字。

请注意,实例和静态属性成员的声明空间是分开的。因此,可以使实例成员和静态属性成员具有相同的名称。

除了重写(如第8.2.3节所述)外,派生类声明与基类成员具有相同名称和种类(实例或静态)的属性成员是错误的。

每个类都会自动包含一个名为“ prototype”的静态属性成员,该成员的类型是类类型的实例化,类型Any用作每个类型参数的类型实参。明确声明名称为“ prototype”的静态属性成员是错误的。

下面是同时包含实例和静态属性成员声明的类的示例:

class Point {  
    constructor(public x: number, public y: number) { }  
    public distance(p: Point) {  
        var dx = this.x - p.x;  
        var dy = this.y - p.y;  
        return Math.sqrt(dx * dx + dy * dy);  
    }  
    static origin = new Point(0, 0);  
    static distance(p1: Point, p2: Point) { return p1.distance(p2); }  
}

类类型“ Point”具有以下成员:

interface Point {  
    x: number;  
    y: number;  
    distance(p: Point);  
}

构造函数“ Point”具有与声明相对应的类型:

var Point: {  
    new(x: number, y: number): Point;  
    origin: Point;  
    distance(p1: Point, p2: Point): number;  
}

8.4.1 成员变量声明

成员变量声明声明实例成员变量或静态成员变量。

MemberVariableDeclaration:
	AccessibilityModifieropt staticopt PropertyName TypeAnnotationopt Initializeropt ;

与成员变量声明关联的类型的确定方式与普通变量声明相同(请参见5.2节)。

实例成员变量声明在类类型中引入成员,并可以选择在类的实例上初始化属性。实例成员变量声明中的初始化程序将为该类的每个新实例执行一次,并且等效于在构造函数中为其分配属性。在实例成员变量的初始化表达式中,它是类的this类型(第3.6.3节)。

静态成员变量声明在构造函数类型中引入属性,并可以选择在构造函数对象上初始化属性。加载包含的脚本或模块时,静态成员变量声明中的初始化程序将执行一次。

实例成员变量的初始化器表达式在类构造函数主体的范围内求值,但不允许引用构造函数的参数或局部变量。这实际上意味着来自外部作用域的与构造函数参数或局部变量同名的实体在实例成员变量的初始化表达式中不可访问。

由于实例成员变量初始化器等效于构造函数中对此属性的分配,因此该示例

class Employee {  
    public name: string;  
    public address: string;  
    public retired = false;  
    public manager: Employee = null;  
    public reports: Employee[] = [];  
}

等价于

class Employee {  
    public name: string;  
    public address: string;  
    public retired: boolean;  
    public manager: Employee;  
    public reports: Employee[];  
    constructor() {  
        this.retired = false;  
        this.manager = null;  
        this.reports = [];  
    }  
}

8.4.2 成员函数声明

成员函数声明声明实例成员函数或静态成员函数。

MemberFunctionDeclaration:
	AccessibilityModifieropt staticopt PropertyName CallSignature { FunctionBody }
	AccessibilityModifieropt staticopt PropertyName CallSignature ;

成员函数声明的处理方式与普通函数声明(第6节)相同,除了在成员函数中具有已知类型之外。

同一成员函数的所有声明必须指定相同的可访问性(公共,私有或受保护)和种类(实例或静态)。

实例成员函数声明以类类型声明一个属性,并将函数对象分配给该类的原型对象上的属性。 在实例成员函数声明的主体中,这是类的this-type(第3.6.3节)的类型。

静态成员函数声明以构造函数类型声明属性,并将函数对象分配给构造函数对象的属性。 在静态成员函数声明的主体中,此类型为构造函数类型。

成员函数可以使用超级属性访问来访问重写的基类成员(第4.9.2节)。 例如

class Point {  
    constructor(public x: number, public y: number) { }  
    public toString() {  
        return "x=" + this.x + " y=" + this.y;  
    }  
}

class ColoredPoint extends Point {  
    constructor(x: number, y: number, public color: string) {  
        super(x, y);  
    }  
    public toString() {  
        return super.toString() + " color=" + this.color;  
    }  
}

在静态成员函数中,这表示在其上调用了静态成员函数的构造函数对象。 因此,对“ new this()”的调用实际上可能会调用派生的类构造函数:

class A {  
    a = 1;  
    static create() {  
        return new this();  
    }  
}

class B extends A {  
    b = 2;  
}

var x = A.create();  // new A()  
var y = B.create();  // new B()

请注意,TypeScript不需要或验证派生的构造函数是基本构造函数的子类型。 换句话说,将“ B”的声明更改为

class B extends A {  
    constructor(public b: number) {  
        super();  
    }  
}

即使从’create’函数调用构造函数时未指定参数(因此将值’undefined’赋予’b’)也不会在示例中引起错误。

8.4.3 成员访问者声明

成员访问器声明声明实例成员访问器或静态成员访问器。

MemberAccessorDeclaration:
	AccessibilityModifieropt staticopt GetAccessor
	AccessibilityModifieropt staticopt SetAccessor

获取和设置访问器的处理方式与对象文字(第4.5节)中的处理方式相同,只是上下文类型在成员访问器声明中永远不可用。

具有相同成员名称的访问者必须指定相同的可访问性。

实例成员访问器声明以类类型声明一个属性,并使用get或set访问器在该类的原型对象上定义一个属性。 在实例成员访问器声明的主体中,这是类的this类型(第3.6.3节)。

静态成员访问器声明在构造函数类型中声明一个属性,并在具有get或set访问器的类的构造函数对象上定义一个属性。 在静态成员访问器声明的主体中,此类型为构造函数类型。

如第8.7.1节所述,在生成的JavaScript中,获取和设置访问器作为对“ Object.defineProperty”的调用而生成。

8.4.4 动态属性声明

如果属性成员声明的PropertyName是不表示众所周知的符号(2.2.3)的计算的属性名称,则该构造被视为动态属性声明。 以下规则适用于动态属性声明:

  • 动态属性声明不会在类类型或构造函数类型中引入属性。
  • 动态属性分配的属性名称表达式必须为Any或String,Number或Symbol原语类型。
  • 如果属性名称表达式的类型为Any或Number原语类型,则与动态属性声明关联的名称被视为数字属性名称。

8.5 索引成员声明

索引成员声明在类类型中引入了索引签名(第3.9.4节)。

IndexMemberDeclaration:
	IndexSignature ;

索引成员声明没有主体,并且不能指定可访问性修饰符。

一个类声明最多可以包含一个字符串索引成员声明和一个数字索引成员声明。 类的所有实例属性成员必须满足3.9.4节中指定的类的索引成员所隐含的约束。

不能为类的静态端声明索引成员。

请注意,在类中包括字符串索引签名几乎没有意义,因为它会约束该类的所有实例属性。 但是,当以类似数组的方式使用类时,数字索引签名可用于控制元素类型。

8.6 装饰者

TODO:文档装饰者。

8.7 代码生成

当输出目标为ECMAScript 2015或更高版本时,在生成的代码中删除类型参数,implementes子句,可访问性修饰符和成员变量声明,但否则以书面形式生成类声明。 如本节所述,当输出目标是ECMAScript 3或5时,将执行更全面的重写。

8.7.1 无extends从句的类

没有extends子句的类将生成等效于以下内容的JavaScript:

var <ClassName> = (function () {  
    function <ClassName>(<ConstructorParameters>) {  
        <DefaultValueAssignments>  
        <ParameterPropertyAssignments>  
        <MemberVariableAssignments>  
        <ConstructorStatements>  
    }  
    <MemberFunctionStatements>  
    <StaticVariableAssignments>  
    return <ClassName>;  
})();

ClassName是类的名称。

ConstructorParameters是用逗号分隔的构造函数参数名称列表。

DefaultValueAssignments是默认属性值分配的序列,对应于为常规函数声明生成的默认值,如6.6节所述。

ParameterPropertyAssignments是一系列分配,对于构造函数中的每个参数属性声明,按声明的顺序依次分配一个

this.<ParameterName> = <ParameterName>;

其中ParameterName是参数属性的名称。

MemberVariableAssignments是一系列分配,对于每个实例成员变量声明,每个初始化声明器均按其声明的顺序进行分配,形式为

this.<MemberName> = <InitializerExpression>;

其中MemberName是成员变量的名称,InitializerExpression是为初始化程序表达式生成的代码。

ConstructorStatements是为构造函数主体中指定的语句生成的代码。

MemberFunctionStatements是一组语句序列,每个成员函数声明或成员访问器声明均按声明顺序进行。

实例成员函数声明生成以下形式的语句

<ClassName>.prototype.<MemberName> = function (<FunctionParameters>) {  
    <DefaultValueAssignments>  
    <FunctionStatements>  
}

和静态成员函数声明生成以下形式的语句

<ClassName>.<MemberName> = function (<FunctionParameters>) {  
    <DefaultValueAssignments>  
    <FunctionStatements>  
}

其中MemberName是成员函数的名称,而FunctionParameters,DefaultValueAssignments和FunctionStatements对应于为常规函数声明生成的那些函数,如6.6节所述。

一个get或set实例成员访问器声明,或一对具有相同名称的get和set实例成员访问器声明,将生成以下形式的语句

Object.defineProperty(<ClassName>.prototype, "<MemberName>", {  
    get: function () {  
        <GetAccessorStatements>  
    },  
    set: function (<ParameterName>) {  
        <SetAccessorStatements>  
    },  
    enumerable: true,  
    configurable: true  
};

一个get或set静态成员访问器声明,或者一对具有相同名称的get和set静态成员访问器声明,生成以下形式的语句

Object.defineProperty(<ClassName>, "<MemberName>", {  
    get: function () {  
        <GetAccessorStatements>  
    },  
    set: function (<ParameterName>) {  
        <SetAccessorStatements>  
    },  
    enumerable: true,  
    configurable: true  
};

其中MemberName是成员访问器的名称,GetAccessorStatements是为get acessor的函数主体中的语句生成的代码,ParameterName是set访问器参数的名称,SetAccessorStatements是为set访问器的函数主体中的语句生成的代码 。 仅当声明了get访问器时才包括’get’属性,而仅当声明了set访问器时才包括’set’属性。

StaticVariableAssignments是一系列语句,对于每个带有初始化程序的静态成员变量声明,每个声明均按声明的顺序进行,形式为

<ClassName>.<MemberName> = <InitializerExpression>;

其中Member Name是静态变量的名称,Initializer Expression是为初始值设定项表达式生成的代码。

8.7.2 带有extends从句的类

具有extends子句的类生成的JavaScript等效于以下内容:

var <ClassName> = (function (_super) {  
    __extends(<ClassName>, _super);  
    function <ClassName>(<ConstructorParameters>) {  
        <DefaultValueAssignments>  
        <SuperCallStatement>  
        <ParameterPropertyAssignments>  
        <MemberVariableAssignments>  
        <ConstructorStatements>  
    }  
    <MemberFunctionStatements>  
    <StaticVariableAssignments>  
    return <ClassName>;  
})(<BaseClassName>);

另外,下面的’__extends’函数在JavaScript源文件的开头生成。 它将所有属性从基本构造函数对象复制到派生构造函数对象(以继承静态成员),并适当地建立派生构造函数对象的’prototype’属性。

var __extends = this.__extends || function(d, b) {  
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];  
    function f() { this.constructor = d; }  
    f.prototype = b.prototype;  
    d.prototype = new f();  
}

BaseClassName是在extends子句中指定的类名。

如果该类没有显式声明的构造函数,则SuperCallStatement采用以下形式:

_super.apply(this, arguments);

否则,如果要求构造函数以超级调用开头(如第8.3.2节所述),则存在SuperCallStatement并采用以下形式:

_super.call(this, <SuperCallArguments>)

其中,SuperCallArguments是超级调用中指定的参数列表。 请注意,此调用在使用初始化程序为参数属性和成员变量生成的代码之前。 构造函数中其他地方的超级调用会生成类似的代码,但为此类调用生成的代码将成为ConstructorStatements部分的一部分。

构造函数中的超级属性访问,实例成员函数或实例成员访问器生成的JavaScript等效于

_super.prototype.<PropertyName>

其中PropertyName是引用的基类属性的名称。 当超级属性访问出现在函数调用中时,生成的JavaScript等效于

_super.prototype.<PropertyName>.call(this, <Arguments>)

其中Arguments是为函数调用中指定的参数列表生成的代码。

静态成员函数或静态成员访问器中的超级属性访问生成的JavaScript等效于

_super.<PropertyName>

其中PropertyName是引用的基类属性的名称。 当超级属性访问出现在函数调用中时,生成的JavaScript等效于

_super.<PropertyName>.call(this, <Arguments>)

其中Arguments是为函数调用中指定的参数列表生成的代码。

codestyle:JavaScript和TypeScript样式指南 代码风格 风格指南 配套 npm软件包列表,可帮助检查项目中的代码样式: JavaScript 打字稿 不推荐使用 (改为使用eslint-config-loris ) 立即下载

相关推荐

translate-serverless-now:使用Vercel Serverless功能和Google API的翻译API

立即翻译无服务器 转换API Vercel无服务器功能 恢复 无服务器功能,可使用@vitalets/google-translate-api翻译文本。 根据构建。 自己部署 请记住,通过使用lib @vitalets/google-translate-api您必须将名为XDG_CONFIG_HOME的环境变量设置为/tmp/.config/才能存储其cookie。 终点 {POST} /翻译 翻译 该请求将其有效负载配置接受为queryString或主体。 请参见下面的请求和响应各自的接口。 interface ITranslateOptions { message : string from : string to : string } interface ITransResult { dst : string src : string } interfac

在static方法中,为什么不能引用类的类型参数?

[size=large]在static方法中,为什么不能引用类的类型参数?[/size] [code] public class Arg< A , B > { public final A a; public final B b; static void setValue(A a,B b){ //This is error. 这里的类型A,B引用的是类中的类型参数。 ...

wgs7909 1068

Opencv实战:答题卡自动识别与评分系统(附完整代码解析)

本文详细介绍了如何使用OpenCV实现答题卡自动识别与评分系统,包含完整的代码解析。通过图像预处理、边缘检测、透视变换和答案识别等关键技术,系统能够快速准确地完成阅卷工作,适用于学校考试、资格认证等多种场景,大幅提升工作效率。

weixin_33737134的博客 415

TS错误信息列表

错误信息列表code类型英文描述中文描述1002错误Unterminated string literal.未终止的字符串文本。1003错误Identifier expected.应为标识符。1005错误'{0}' expected.应为“{0}”。1006错误A file cannot have a reference to itself.文件不能引用自身。1009错误Trailing comm...

Jinmy的博客 9万+

共聚焦显微镜的光源、工作原理与选型

共聚焦显微镜作为科研与工业领域中重要的微观成像工具,凭借光源的精准适配性、光学切片技术的三维成像能力,以及对不同工业场景的定制化适配潜力,为半导体检测、工业部件分析、智能制造升级提供了关键技术支撑。深入理解其光源特性、工作原理与选型逻辑,能帮助工程师与技术人员精准匹配设备与生产需求,既保障微观检测的精度与效率,又为产业优化、技术创新筑牢微观观测的基础。

PhotonixBay的博客 1536

从零到一:基于Rocky Linux 9的Kubernetes高可用集群部署实战

本文提供了一份基于Rocky Linux 9操作系统,从零开始部署Kubernetes高可用集群的完整实战指南。详细讲解了包括系统初始化、容器运行时配置、使用kubeadm工具进行集群初始化、节点加入以及Calico网络插件安装在内的核心步骤,并针对国内网络环境提供了镜像加速等优化方案,旨在帮助读者构建一个稳定可靠的生产级K8s环境。

weixin_29197835的博客 134

前端(六)——TypeScript在前端中的重要性与应用

TypeScript 是一种开源的编程语言,它是 JavaScript 的一个超集。由于 TypeScript 扩展了 JavaScript,并添加了静态类型系统和其他特性,因此它可以被视为 JavaScript 的增强版。TypeScript 被设计用来解决 JavaScript 在大型应用开发方面的一些困难和限制。它通过引入静态类型、类、接口、模块化等特性,提供了更强大的工具和功能,有助于构建可维护、可扩展的应用程序。⭐⭐⭐TS的特点包括:静态类型检查。

杜永康的博客 3021

写一个b站爬虫(思路)

part 0 安装 scrapy, requests part 1 信息获取 打开番剧索引链接(https://www.bilibili.com/anime/index/) F12控制台,选中NETWORK,来到xhr文件,我们可以找到了存放番剧json的地方

kou的博客 484

[TypeScript] 编程实践之1: Google的TypeScript代码风格1:介绍

TypeScript语言规范1 介绍1.1 环境声明1.2 函数类型1.3 对象类型1.4 结构子类型化1.5 上下文类型推断1.6 类1.7 枚举类型1.8 字符串参数重载1.9 通用类型和功能1.10 命名空间1.11 模块 版本1.8 2016年1月 Microsoft自2012年10月1日起根据Open Web Foundation最终规范协议版本1.0(“ OWF 1.0”)提供此规范。OWF 1.0可以从http://www.openwebfoundation.org/legal/the-owf

魔豆(Magicbean)的博客 1398

免Root抓包神器Packet Capture:安卓App数据捕获全攻略

本文详细介绍了免Root安卓抓包神器Packet Capture的安装与使用全攻略。通过利用安卓系统的VPN Service API,该工具无需Root权限即可捕获并解密App的HTTP/HTTPS网络流量。文章从核心原理、证书安装、实战抓包步骤到结果分析与常见问题排查,提供了完整指南,是移动端开发、安全测试和数据分析的实用利器。

weixin_29232507的博客 1072

【OpenClaw从入门到精通】第34篇:医疗AI的“Agent OS”时代:基于WiseClaw构建医院专属智能体平台(2026实测版)

2026年医疗AI迈入实战落地新阶段,全球首个医疗OpenClaw平台WiseClaw正式发布,香港中文大学(深圳)医院完成业内首个私有化部署。本文基于真实医疗场景需求与公开技术资料,系统拆解医疗智能体平台的建设逻辑:从医疗Agent OS的五大核心特性切入,详解门诊病历质控、用药审查、医院运行管理三大临床场景的智能体搭建流程,提供完整的私有化部署代码、安全配置方案与实操演示。文章兼顾新手入门与进阶需求,严格遵循医疗合规要求,强调“只读不写+人工复核”原则,所有方案均经过虚拟实测验证。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 786

[TypeScript] 编程实践之1: Google的TypeScript代码风格13:语法

TypeScript语言规范A 语法A.1 类型A.2 表达式A.3 语句A.4 函数A.5 接口A.6 类A.7 枚举A.8 命名空间A.9 Script和ModulesA.10 Ambient A 语法 本附录包含在主文档中找到的语法摘要。 如2.1节所述,TypeScript语法是ECMAScript 2015语言规范(特别是ECMA-262标准,第6版)中定义的语法的超集,本附录仅列出从ECMAScript语法中新增或修改的产品。 A.1 类型 TypeParameters: < TypeP

魔豆(Magicbean)的博客 706

Yield Management软件:Lam Research二次开发_(5).缺陷分析与分类方法

在半导体制造过程中,缺陷分析和分类是提高良率管理(Yield Management)的关键步骤。通过准确地识别和分类缺陷,可以更好地理解工艺过程中的问题,从而采取有效的措施来提高生产效率和产品质量。本节将详细介绍缺陷分析和分类的方法,包括缺陷检测、特征提取、分类算法及其在Lam Research软件中的应用。

2401_87715305的博客 686

[TypeScript] 编程实践之1: Google的TypeScript代码风格12:Ambients

TypeScript语言规范12 Ambients12.1 Ambients声明12.1.1 Ambient变量声明12.1.2 Ambient函数声明12.1.3 Ambient类声明12.1.4 Ambient枚举声明12.1.5 Ambient命名空间声明12.2 Ambient模块声明 12 Ambients 环境声明用于在现有JavaScript代码上提供静态类型。 环境声明与常规声明的不同之处在于,不会为它们生成JavaScript代码。 环境声明不是引入新的变量,函数,类,枚举或命名空间,而是

魔豆(Magicbean)的博客 700

14、微电网控制方法与建模分析

本文详细探讨了微电网的控制方法与建模分析,包括逆变器的小信号状态空间模型、网络模型、负载模型及其组合形成的完整微电网模型。通过对系统特征值和灵敏度因子的分析,揭示了不同模式与系统参数之间的关系。文章还提出了多个研究问题,如岛式系统控制器设计、风力发电控制、并网变换器控制等,为微电网的稳定性分析和优化控制提供了理论支持和实践方向。

elastic6hunter的博客 122

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

[TypeScript] 编程实践之1: Google的TypeScript代码风格5:语句

TypeScript语言规范5 语句5.1 块5.2 变量语句5.2.1 简单变量声明5.2.2 析构变量声明5.2.3 implied类型5.3 let和const声明5.4 If,Do和While语句5.5 for语句5.6 for-in语句5.7 For-of语句5.8 Continue语句5.9 Break语句5.10 Return语句5.11 With语句5.12 Switch语句5.13 Throw语句5.14 Try语句 5 语句 本章介绍TypeScript为JavaScript语句提供的静

魔豆(Magicbean)的博客 1371

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

[TypeScript] 编程实践之1: Google的TypeScript代码风格3:类型

TypeScript语言规范3 类型3.1 Any类型3.2 基本类型3.2.1 Number类型3.2.2 Boolean类型3.2.3 String类型3.2.4 Symbol类型3.2.5 Void类型3.2.6 Null类型3.2.7 Undefined类型3.2.8 Enum类型3.2.9 String类型3.3 Object类型3.3.1 命名类型引用3.3.2 Array类型3.3.3 Tuple类型3.3.4 Function类型3.3.5 Constructor类型3.3.6 Member

魔豆(Magicbean)的博客 786

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

[TypeScript] 编程实践之1: Google的TypeScript代码风格2:基本概念

TypeScript语言规范2 基本概念2.1 语法约定2.2 命名2.2.1 保留字2.2.2 属性命名2.2.3 计算属性命名2.3 声明2.4 范围 2 基本概念 本文档的其余部分是TypeScript编程语言的正式规范,旨在作为ECMAScript 2015 Language Specification(特别是ECMA-262标准,第6版)的附件来阅读。 本文档描述了TypeScript所添加的语法,以及TypeScript编译器执行的编译时处理和类型检查,但是由于ECMAScript规范涵盖了该内

魔豆(Magicbean)的博客 607

[TypeScript] 编程实践之1: Google的TypeScript代码风格11:Script和Modules

TypeScript语言规范11 Scripts和Modules11.1 程序和源文件11.1.1 源文件依赖11.2 Script11.3 Modules11.3.1 Module命名11.3.2 导入声明11.3.3 Import Require声明11.3.4 Export声明11.3.4.1 Export修饰符11.3.4.2 Export Default声明11.3.4.3 Export list声明11.3.4.4 导出成员集11.3.5 Export赋值11.3.6 CommonJS模块11.

魔豆(Magicbean)的博客 854

Google 编程风格:C++、Python、JavaScript、Shell、TypeScript

Google 编程风格:C++、Python、JavaScript、Shell、TypeScript

freeking101的博客 5万+

[TypeScript] 编程实践之1: Google的TypeScript代码风格9:枚举

TypeScript语言规范9 枚举9.1 枚举声明9.2 枚举成员9.3 声明合并9.4 常量枚举声明9.5 代码生成 9 枚举 枚举类型是Number原语类型的独特子类型,具有一组关联的命名常量,这些常量定义了枚举类型的可能值。 9.1 枚举声明 枚举声明声明一个枚举类型和一个枚举对象。 EnumDeclaration: constopt enum BindingIdentifier { EnumBodyopt } EnumDeclaration在包含的声明空间中引入了命名类型(枚举类型)和命名值(

魔豆(Magicbean)的博客 528

[TypeScript] 编程实践之1: Google的TypeScript代码风格7:接口

TypeScript语言规范7 接口7.1 接口声明7.2 声明合并7.3 接口扩展类7.4 动态类型检查 7 接口 接口提供了命名和参数化对象类型并将现有命名对象类型组合为新对象的能力。 接口没有运行时表示—它们纯粹是编译时构造。 接口对于记录和验证所需的属性形状,作为参数传递的对象以及从函数返回的对象特别有用。 因为TypeScript具有结构类型系统,所以具有一组特定成员的接口类型被认为与具有相同成员组的另一个接口类型或对象类型文字相同(并且可以替代)(请参阅第3.11.2节)。 类声明可以在自己的I

魔豆(Magicbean)的博客 468

[TypeScript] 编程实践之1: Google的TypeScript代码风格10:命名空间

TypeScript语言规范10 命名空间10.1 命名空间声明10.2 命名空间体10.3 导入别名声明10.4 导出声明10.5 声明合并10.6 代码生成 10 命名空间 命名空间提供了一种在命名容器的层次结构中组织代码和声明的机制。 命名空间具有命名的成员,每个成员表示一个值,一个类型或一个命名空间,或其某种组合,这些成员可以是本地的也可以是导出的。 命名空间的主体对应于一次执行的功能,从而提供了一种机制,用于确保局部状态并确保隔离。 命名空间可以看作是立即调用的函数表达(IIFE)模式的形式化形式

魔豆(Magicbean)的博客 562

[TypeScript] 编程实践之1: Google的TypeScript代码风格6:函数

TypeScript语言规范6 函数6.1 函数声明6.2 函数重载6.3 函数实现6.4 析构参数声明6.5 通用函数6.6 代码生成6.7 生成函数6.8 异步函数6.9 类型保护函数 6 函数 TypeScript扩展了JavaScript函数,以包括类型参数,参数和返回类型注释,重载,默认参数值和rest参数。 6.1 函数声明 扩展了函数声明,以允许在重载声明中省略函数主体。 FunctionDeclaration: ( Modified ) function BindingIdentifier

魔豆(Magicbean)的博客 484

[TypeScript] 编程实践之1: Google的TypeScript代码风格4:表达式

TypeScript语言规范4 表达式4.1 值和引用4.2 this关键字4.3 标识符4.4 文法4.5 Object文法4.6 数组文法4.7 模板文法4.8 括弧4.9 super关键字4.9.1 父类super调用4.9.2 父类属性存取4.10 函数表达式4.11 箭头函数4.12 Class表达式4.13 属性存取4.14 new操作算子4.15 函数调用4.15.1 重载解决方案4.15.2 类型参数推导4.15.3 语法歧义4.16 类型断言4.17 JSX表达式4.18 一元运算符4.1

魔豆(Magicbean)的博客 979

如何用gts在5分钟内统一团队TypeScript代码风格 [特殊字符]

还在为团队中TypeScript代码风格不一致而烦恼吗?每次代码评审都要花大量时间讨论缩进、引号、分号?gts就是你的终极解决方案!这款由Google开发的TypeScript风格指南、格式化器和linter,能让你在5分钟内为团队建立统一的代码规范。✨ ## 为什么选择gts?🤔 gts是Google官方的**TypeScript代码风格工具**,它集成了业界最佳实践,让你无需配置就能享受

gitblog_00749的博客 990
上一篇: [TypeScript] 编程实践之1: Google的TypeScript代码风格7:接口
下一篇: [TypeScript] 编程实践之1: Google的TypeScript代码风格9:枚举
魔豆Magicbean
博客等级 码龄19年 146粉丝 742原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值