TypeScript 静态属性和方法

注意: 如果您是 TypeScript 新手,请先查看我们的 TypeScript 入门 教程。


在 TypeScript 中,static 关键字用于创建静态属性和方法。

静态属性和方法属于类本身,而不属于类的任何单个实例。换句话说,它们在类的所有实例之间共享。

静态属性和方法对于所有实例都通用的数据或行为很有用。


TypeScript 静态属性

要创建静态属性,我们在属性名之前使用 static 关键字。例如,

class Dog {
    // Declare a static property
    static bark: string = "Woof!";

    constructor(private name: string, private owner: string) {}
    
    dogIntro(): string {
        return `${this.name} loves its owner, ${this.owner}, and says ${Dog.bark}`;
    }
}

// Create instances of Dog class
let dog1 = new Dog("Wolfie", "Jessica");
let dog2 = new Dog("Honey", "James");

console.log(dog1.dogIntro());
console.log(dog2.dogIntro());

// Access the static property outside the class
console.log(`All dogs say ${Dog.bark}`);

输出

Wolfie loves its owner, Jessica, and says Woof!
Honey loves its owner, James, and says Woof!
All dogs say Woof!

在这里,我们在 Dog 类中创建了一个静态属性 bark。因此,bark 的单个副本由所有 Dog 实例共享。

另一方面,每个 Dog 实例都有自己的非静态属性和方法副本,即 nameownerdogIntro()

All Instances Share a Static Property
所有实例共享一个静态属性

使用类名访问静态属性

在前面的示例中,请注意如何在类内部和外部访问静态属性

class Dog {
    ... ... ...

    // Access the static property inside the class    
    dogIntro(): string {
        return `${this.name} loves its owner, ${this.owner}, and says ${Dog.bark}`;
    }
}

... ... ...

// Access the static property outside the class
console.log(`All dogs say ${Dog.bark}`);

通常,我们在类内部使用 this 访问非静态属性,而在类外部使用对象名(dog1dog2)访问这些属性。

但是,我们使用类名来访问静态属性,因为它们属于类本身,而不是类的各个实例。

// Valid way to access static property
Dog.bark

// Invalid ways to access static property (inside class)
this.bark

// Invalid ways to access static property (outside class)
dog1.bark
dog2.bark

注意:您可以使用 this 在静态方法中访问静态属性。


示例 1:TypeScript 静态属性

class Employee {
    static headcount: number = 0; // Static property

    constructor(private name: string, private jobTitle: string) {
        // Increment headcount whenever a new instance is created
        Employee.headcount++;
    }
    
    getInfo(): void {
        console.log(`Employee: ${this.name}`);
        console.log(`Job Title: ${this.jobTitle}\n`);
    }
}

let employee1 = new Employee("John Doe", "Developer");
let employee2 = new Employee("Jane Doe", "Designer");

// Print the employee details
employee1.getInfo();
employee2.getInfo();

// Print the static property
console.log(`Headcount: ${Employee.headcount}`);

输出

Employee: John Doe
Job Title: Developer

Employee: Jane Doe
Job Title: Designer

Headcount: 2

在此程序中,我们创建了一个静态属性 headcount,每次创建 Employee 类的实例时都会增加它。

最初,headcount 的值为 0

由于我们接着创建了两个 Employee 实例(employee1employee2),因此 headcount 的最终值为 2


TypeScript 静态方法

与静态属性一样,静态方法属于类本身,而不是各个实例。

要创建静态方法,我们在方法名之前使用 static 关键字。例如,

class Dog {
    private static bark: string = "Woof!";

    constructor(private name: string, private owner: string) {}
    
    dogIntro(): string {
        return `${this.name} loves its owner, ${this.owner}, and says ${Dog.bark}`;
    }

    // Create a static method that returns the static property
    static getBark(): string {
        return Dog.bark;
    }
}

// Create instances of Dog class
let dog1 = new Dog("Wolfie", "Jessica");
let dog2 = new Dog("Honey", "James");

console.log(dog1.dogIntro());
console.log(dog2.dogIntro());

// Access the static method
let dogBark: string = Dog.getBark();

console.log(`All dogs say ${dogBark}`);

输出

Wolfie loves its owner, Jessica, and says Woof!
Honey loves its owner, James, and says Woof!
All dogs say Woof!

在这里,静态方法 getBark() 返回私有静态属性 bark 的值。

在类外部,我们通过使用类名而不是对象 dog1dog2 来访问静态方法。

// Access the static method
let dogBark: string = Dog.getBark();

示例 2:TypeScript 静态方法

class Circle {

    // Static constant
    static readonly PI: number = 3.14159;

    static calculateArea(radius: number): number {
        return Circle.PI * radius * radius;
    }
}

// Access static property
console.log(`Value of PI: ${Circle.PI}`);

// Access static method
let area: number = Circle.calculateArea(5);
console.log(`Area of Circle: ${area}`);

输出

Value of PI: 3.14159
Area of Circle: 78.53975

这里,PI 是一个静态常量,calculateArea() 是一个静态方法。因此,它们都由 Circle 类的所有实例共享。

注意:我们使用 readonly 访问修饰符将类属性声明为常量。另一方面,const 关键字用于将普通变量声明为常量。


更多关于 TypeScript 静态

无需创建任何实例即可访问静态属性和方法。

由于静态属性和方法属于类本身,因此它们不依赖于类实例的存在。

因此,即使您没有创建类的任何实例,也可以访问它们。例如,

class Dog {
    static bark: string = "Woof!";

    constructor(private name: string, private owner: string) {}
    
    dogIntro(): string {
        return `${this.name} loves its owner, ${this.owner}.`;
    }

    // Use 'this' inside a static method
    static getBark(): string {
        return Dog.bark;
    }
}

// Access static property
console.log(`Say ${Dog.bark}`);

// Access static method
let dogBark: string = Dog.getBark();
console.log(`All dogs say ${dogBark}`);

输出

Say Woof!
All dogs say Woof!

在这里,我们在没有创建任何 Dog 实例的情况下访问了静态属性和方法。

但是,没有实例我们无法访问非静态属性和方法。

// Error: Property 'dogIntro' does not exist on type 'typeof Dog'.
console.log(Dog.dogIntro());
在静态方法中,“this”指的是类,而不是实例。

1. 非静态方法中的“this”

当您在非静态方法中使用 this 时,它指的是类的单个实例。例如,

class Dog {
    constructor(private name: string, private owner: string) {}
    
    dogIntro(): string {
        return `${this.name} loves its owner, ${this.owner}.`;
    }
}

let dog1 = new Dog("Wolfie", "Jessica");
let dog2 = new Dog("Honey", "James");

console.log(dog1.dogIntro());
console.log(dog2.dogIntro());

// Output:
// Wolfie loves its owner, Jessica.
// Honey loves its owner, James.

创建 dog1 时。

  • this.name 指的是 dog1.name
  • this.owner 指的是 dog1.owner

创建 dog2 时。

  • this.name 指的是 dog2.name
  • this.owner 指的是 dog2.owner

2. 静态方法中的“this”

但是,在静态方法中,this 指的是类本身,而不是任何单个实例。例如,

class Dog {
    private static bark: string = "Woof!";

    constructor(private name: string, private owner: string) {}
    
    dogIntro(): string {
        return `${this.name} loves its owner, ${this.owner}.`;
    }

    // Use 'this' inside a static method
    static getBark(): string {
        return this.bark;
    }
}

let dog1 = new Dog("Wolfie", "Jessica");
let dog2 = new Dog("Honey", "James");

console.log(dog1.dogIntro());
console.log(dog2.dogIntro());

let dogBark: string = Dog.getBark();
console.log(`All dogs say ${dogBark}`);

输出

Wolfie loves its owner, Jessica.
Honey loves its owner, James.
All dogs say Woof!

这里,我们在静态方法 getBark() 中使用了 this。

static getBark(): string {
    return this.bark;
}

在这种情况下,创建多少个 Dog 实例或创建什么实例都不重要。在所有情况下,this.bark 始终指向 Dog.bark,因为它在静态方法中使用。

静态方法无法访问非静态属性。

静态方法无法访问非静态属性,因为非静态属性属于类的各个实例。

因此,在创建对象之前,非静态属性不会生效。例如,

class Dog {

    // Non-static property
    breed: string;

    constructor(breed: string) {
        this.breed = breed;
    }

    // Static method
    static getBreed(): void {
    
        // Error because getBreed() is static but breed is not
        console.log(this.breed);
    }
}

这里,静态方法 getBreed() 无法访问非静态属性 breed,因为静态方法中的 this 指的是类而不是类的实例。

但是,breed(作为非静态属性)属于类实例。因此,getBreed() 无法访问它。

非静态方法可以访问静态属性。

虽然静态方法不能访问非静态属性,但非静态方法可以轻松访问静态属性。例如,

class Dog {
    // Declare a static property
    static bark: string = "Woof!";

    constructor(private name: string, private owner: string) {}
    
    // Non-static method that accesses
    // both static and non-static properties
    dogIntro(): string {
        return `${this.name} loves its owner, ${this.owner}, and says ${Dog.bark}`;
    }
}

let dog1 = new Dog("Wolfie", "Jessica");
console.log(dog1.dogIntro());

// Output: Wolfie loves its owner, Jessica, and says Woof!

这里,非静态 dogIntro() 方法能够访问静态属性 bark

这是因为实例方法可以访问 this(实例),并且还可以使用类名(Dog.bark)访问静态成员。

这是允许的,因为静态成员可以从类本身访问。


阅读更多

你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战