TypeScript 如何做静态成员
在做前端项目的时候,你有没有遇到过这种情况:比如要写一个工具类,里面需要存一些全局共用的配置,或者一个统计方法,不管创建多少个这个类的实例,这个方法都只需要运行一次——如果用普通的 JavaScript,你可能会把这些变量挂在 window 上,或者写个全局函数,结果很容易不小心被别的代码覆盖,或者逻辑乱成一团。这时候 TypeScript 的静态成员就能帮上大忙,而且用法特别简单,咱们用生活化的例子慢慢说。
什么是静态成员?用奶茶店举例子就懂
你可以把一个类想象成一家奶茶店,普通成员就像每一杯奶茶的“专属属性”——比如一杯少糖的珍珠奶茶,它的甜度、配料都是这一杯独有的,不同的奶茶,甜度可能不一样。而静态成员呢,就像这家奶茶店的“统一规定”——不管做多少杯奶茶,这个店的营业时间、取餐地址、客服电话都是固定的,属于整个店本身,不属于某一杯具体的奶茶。

对应的代码里,静态成员是用 static 关键字标记的,不管你创建了多少个类的实例,静态成员都只有一份,存在类本身里,不会被实例共享。
怎么定义静态属性?给奶茶店加统一信息
假设我们要写一个奶茶店的类,先试试普通属性,再对比静态属性的用法,你就明白区别了:
`typescript
class MilkTeaShop {
// 普通属性:每杯奶茶的专属信息
name: string; // 每杯奶茶的名字
price: number; // 每杯奶茶的价格
// 静态属性:整个店的统一信息
static businessHours = "10:00-22:00"; // 营业时间,全店通用
static address = "XX街XX号"; // 取餐地址,不会随奶茶变化
constructor(name: string, price: number) {
this.name = name;
this.price = price;
}
}
`
这时候你试试调用:const myTea = new MilkTeaShop("珍珠奶茶", 12),你会发现 myTea.businessHours 是报错的——因为静态属性是属于类本身的,不是实例的,得用 类名.静态属性 来访问,比如 MilkTeaShop.businessHours,这样就不会和具体某杯奶茶的属性混了,也不会不小心改到全局变量。
怎么用静态方法?写不重复的统一功能
除了属性,静态方法也很常用。还是奶茶店的例子,比如全店统一的“查看营业时间”“计算配送费”,这些功能不需要某一杯奶茶来运行,只要知道店的信息就够了,这时候用静态方法就很合适:
`typescript
class MilkTeaShop {
static businessHours = "10:00-22:00";
static address = "XX街XX号";
// 静态方法:查看营业时间,全店通用
static showBusinessHours() {
return 本店营业时间是${this.businessHours};
}
// 静态方法:根据距离计算配送费,统一规则
static calculateDeliveryFee(distance: number) {
return distance < 2 ? 5 : 8; // 2公里内5元,超过8元
}
}
`
调用的时候同样用类名:MilkTeaShop.showBusinessHours(),不管你买多少杯奶茶,这个方法的规则都不会变。如果用普通方法写,每次创建实例都要重新写一遍计算配送费的逻辑,不仅重复,还容易写错。
静态成员的小注意事项
有两个小细节要记一下,避免踩坑:
第一,静态方法里不能用 this 指向实例,只能指向类本身——因为静态成员是属于类的,不是实例的,所以静态方法里只能访问其他静态成员,不能访问普通属性。比如你在 showBusinessHours 里写 this.name 就会报错,因为 name 是每杯奶茶的专属属性,不是店的统一属性。
第二,静态属性虽然方便,但不要滥用——如果只是临时用的变量,没必要都写成静态的,静态成员会一直存在内存里,不会被自动回收,只有当这个变量确实是“整个类共用、不会随实例变化”的时候,再用静态成员。
这样用下来,你会发现静态成员既能把全局的统一信息和功能归类,又不会污染全局变量,写出来的代码更整洁,也不容易出bug。