TypeScript 类的静态成员与静态方法

本文献给:

已掌握 TypeScript 类基础、继承、多态、抽象类等知识的开发者。本文将带你学习类的静态成员(static 属性)和静态方法,包括访问限制、与实例成员的区别,以及工具类设计中的典型应用。

你将学到:

  1. 静态属性与静态方法的定义
  2. 静态成员与实例成员的区别
  3. 静态成员的访问限制(public/private/protected
  4. 静态成员在继承中的行为
  5. 工具类与工厂模式的静态方法设计

目录

一、静态成员的定义

使用 static 关键字定义类的静态属性和静态方法。静态成员属于类本身,而不是类的实例。

typescript 复制代码
class Circle {
    static pi: number = 3.14159;
    
    static calculateArea(radius: number): number {
        return this.pi * radius * radius;
    }
    
    radius: number;
    constructor(radius: number) {
        this.radius = radius;
    }
    
    getArea(): number {
        return Circle.calculateArea(this.radius);
    }
}

console.log(Circle.pi);                    // 3.14159
console.log(Circle.calculateArea(5));      // 78.53975

const c = new Circle(5);
console.log(c.getArea());                  // 78.53975
// console.log(c.pi);                      // ❌ 实例不能访问静态属性

静态成员通过类名直接访问,实例无法访问静态成员(但可以通过 this.constructor 间接访问)。

二、静态方法与实例方法的区别

特性 静态方法 实例方法
归属 类本身 类的实例
调用方式 ClassName.method() instance.method()
访问实例成员 不能直接访问(无 this 指向实例) 可以访问实例成员
访问静态成员 可以(通过 this 或类名) 可以(通过类名)
使用场景 工具函数、工厂方法、单例模式 操作实例数据
typescript 复制代码
class Example {
    static staticProp = 0;
    instanceProp = 1;
    
    static staticMethod() {
        console.log(this.staticProp);  // OK
        // console.log(this.instanceProp);  // ❌ 静态方法中不能访问实例属性
    }
    
    instanceMethod() {
        console.log(Example.staticProp);  // OK
        console.log(this.instanceProp);   // OK
    }
}

三、静态成员的访问修饰符

静态成员可以结合 publicprivateprotected 使用,控制访问范围。

typescript 复制代码
class Database {
    private static instance: Database;
    private constructor() {}
    
    static getInstance(): Database {
        if (!Database.instance) {
            Database.instance = new Database();
        }
        return Database.instance;
    }
    
    query(sql: string) {
        console.log(`Executing: ${sql}`);
    }
}

const db = Database.getInstance();
db.query("SELECT * FROM users");
// const db2 = new Database();  // ❌ 构造函数私有

3.1 protected 静态成员

protected static 可以在子类中访问。

typescript 复制代码
class Base {
    protected static config = { version: "1.0" };
}

class Derived extends Base {
    static showConfig() {
        console.log(this.config);  // OK
    }
}

Derived.showConfig();  // { version: "1.0" }

四、静态成员在继承中的行为

静态成员也会被继承,子类可以访问父类的静态成员。

typescript 复制代码
class Parent {
    static value = 10;
    static getValue() {
        return this.value;
    }
}

class Child extends Parent {
    static value = 20;  // 覆盖
}

console.log(Parent.getValue());  // 10
console.log(Child.getValue());   // 20(静态方法中的 this 指向调用者)

静态方法中的 this 指向调用该方法的类(而不是定义时的类),因此子类可以覆盖静态属性并影响方法返回值。

4.1 类名与 this 的区别

typescript 复制代码
class A {
    static name = "A";
    static getName() {
        return this.name;
    }
    static getNameHard() {
        return A.name;  // 始终返回 A.name
    }
}

class B extends A {
    static name = "B";
}

console.log(B.getName());      // "B"(this 指向 B)
console.log(B.getNameHard());  // "A"(固定使用 A.name)

五、常见使用场景

5.1 工具类

将相关工具函数组织为静态方法,无需实例化。

typescript 复制代码
class MathUtils {
    static clamp(value: number, min: number, max: number): number {
        return Math.min(max, Math.max(min, value));
    }
    
    static randomRange(min: number, max: number): number {
        return min + Math.random() * (max - min);
    }
    
    static degToRad(deg: number): number {
        return deg * Math.PI / 180;
    }
}

console.log(MathUtils.clamp(150, 0, 100));   // 100

5.2 工厂方法

静态方法作为工厂创建实例,可以封装复杂的创建逻辑或缓存。

typescript 复制代码
class User {
    private constructor(public id: number, public name: string) {}
    
    private static cache = new Map<number, User>();
    
    static create(id: number, name: string): User {
        if (this.cache.has(id)) {
            return this.cache.get(id)!;
        }
        const user = new User(id, name);
        this.cache.set(id, user);
        return user;
    }
}

const u1 = User.create(1, "Alice");
const u2 = User.create(1, "Bob");   // 返回缓存的 Alice
console.log(u1 === u2);  // true

5.3 单例模式

确保一个类只有一个实例。

typescript 复制代码
class Logger {
    private static instance: Logger;
    private logs: string[] = [];
    
    private constructor() {}
    
    static getInstance(): Logger {
        if (!Logger.instance) {
            Logger.instance = new Logger();
        }
        return Logger.instance;
    }
    
    log(msg: string) {
        this.logs.push(msg);
        console.log(msg);
    }
    
    getLogs() {
        return [...this.logs];
    }
}

const logger1 = Logger.getInstance();
const logger2 = Logger.getInstance();
console.log(logger1 === logger2);  // true

六、常见错误与注意事项

6.1 静态方法中访问实例成员

typescript 复制代码
class Demo {
    name = "demo";
    static test() {
        // console.log(this.name);  // ❌ 静态方法中 this 是类,没有 name
    }
}

如果需要访问实例,可以将实例作为参数传入。

6.2 实例中访问静态成员时混淆

实例方法中访问静态成员推荐使用类名,而不是 this,因为 this 可能被覆盖(尤其在继承中)。

typescript 复制代码
class Parent {
    static value = 10;
    getStatic() {
        return (this.constructor as any).value;  // 不推荐,麻烦且容易出错
    }
    getStaticBetter() {
        return Parent.value;  // 明确使用类名
    }
}

6.3 子类覆盖静态属性时影响父类静态方法中的 this

如果父类静态方法使用 this.xxx,子类覆盖静态属性后,调用子类该方法会得到子类属性值。这可能符合预期,也可能不是。根据需求选择使用 ClassName 还是 this

6.4 在静态块中初始化(ES2022+)

TypeScript 支持静态块(需 target ES2022 或更高),用于复杂静态初始化。

typescript 复制代码
class Config {
    static settings: Record<string, string>;
    static {
        // 静态块在类初始化时执行
        this.settings = JSON.parse(localStorage.getItem("config") || "{}");
    }
}

6.5 泛型类中的静态成员

静态成员不能引用类的泛型类型参数,因为静态成员属于类而非实例,类型参数在实例化时才确定。

typescript 复制代码
class Generic<T> {
    // static value: T;  // ❌ 静态成员不能使用泛型参数
}

七、综合示例

typescript 复制代码
// 任务管理器:使用静态成员管理全局任务计数和配置
class Task {
    private static taskCount = 0;
    private static readonly MAX_TASKS = 100;
    
    static get count() {
        return Task.taskCount;
    }
    
    static canCreate(): boolean {
        return Task.taskCount < Task.MAX_TASKS;
    }
    
    static reset() {
        Task.taskCount = 0;
    }
    
    private id: number;
    constructor(public title: string) {
        if (!Task.canCreate()) {
            throw new Error("Task limit reached");
        }
        this.id = ++Task.taskCount;
    }
    
    getId() {
        return this.id;
    }
}

// 子类继承静态成员
class UrgentTask extends Task {
    static override canCreate(): boolean {
        return Task.count < 20;  // 紧急任务限制更严格
    }
    
    constructor(title: string, public priority: number) {
        super(title);
    }
}

try {
    for (let i = 0; i < 50; i++) {
        new Task(`Task ${i}`);
    }
} catch (e) {
    console.log(e.message);  // "Task limit reached"
}

console.log(Task.count);    // 100
Task.reset();
console.log(Task.count);    // 0

// 工厂静态方法
class Point {
    constructor(public x: number, public y: number) {}
    
    static fromPolar(radius: number, angle: number): Point {
        return new Point(radius * Math.cos(angle), radius * Math.sin(angle));
    }
    
    static fromObject(obj: { x: number; y: number }): Point {
        return new Point(obj.x, obj.y);
    }
}

const p1 = Point.fromPolar(5, Math.PI / 4);
const p2 = Point.fromObject({ x: 10, y: 20 });
console.log(p1, p2);

八、小结

概念 语法示例 说明
静态属性 static count = 0 属于类本身的属性
静态方法 static getCount() { return this.count; } 属于类本身的方法
访问静态成员 ClassName.property 在外部和实例方法中通过类名访问
继承中的静态成员 子类可访问/覆盖父类静态成员 静态方法中的 this 指向子类
私有静态成员 private static instance 用于单例模式
使用场景 工具方法、工厂、缓存、单例 无需实例化的功能

觉得文章有帮助?别忘了:

👍 点赞 👍 -- 给我一点鼓励

⭐ 收藏 ⭐ -- 方便以后查看

🔔 关注 🔔 -- 获取更新通知


标签: #TypeScript #静态成员 #静态方法 #面向对象 #学习笔记 #前端开发

相关推荐
微学AI1 小时前
一根针指向所有方向:挂谷猜想对 LLM Agent 技能-记忆架构的启示
开发语言·人工智能·架构·挂谷猜想
豆瓣鸡2 小时前
算法日记 - Day3
java·开发语言·算法
夏殇之殁2 小时前
包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...
服务器·前端·javascript
韭菜炒鸡肝天2 小时前
VTK开发笔记(一):VTK介绍,Qt..+VSx+VTK.编译
开发语言·笔记·qt
Aaron - Wistron3 小时前
Web API C# (Furion版)带 单元测试
开发语言·后端·c#
新中地GIS开发老师3 小时前
WebGIS开发学生作品|低空航天管理与航线规划系统
前端·javascript·webgis·三维gis开发
丙氨酸長鏈4 小时前
Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例
前端·javascript·数据库
Dxy12393102164 小时前
Python项目打包成EXE完整教程(PyInstaller实战避坑)
开发语言·python
0566464 小时前
Python康复训练——常用标准库
开发语言·python·学习
骊城英雄4 小时前
基于C#+avalonia ui实现的跨平台点胶机灌胶监控控制上位机软件
开发语言·ui·c#