主题
静态属性和静态方法
静态成员属于类本身,而不属于某个实例。它适合表达“整个类共享的能力”或“和实例无关的辅助能力”。
什么是静态成员
在 class 中,使用 static 声明的属性和方法就是静态成员:
js
class User {
static type = 'user'
static createGuest() {
return new User('Guest')
}
constructor(name) {
this.name = name
}
}这里的 type 和 createGuest() 都挂在 User 这个类本身上。
调用方式
静态成员通过类名访问,而不是通过实例访问:
js
class User {
static type = 'user'
static createGuest() {
return new User('Guest')
}
constructor(name) {
this.name = name
}
}
console.log(User.type) // 'user'
const guest = User.createGuest()
console.log(guest.name) // 'Guest'实例不能直接访问静态成员:
js
const user = new User('Lee')
console.log(user.type) // undefined
// user.createGuest() // TypeError静态方法适合做什么
静态方法最常见的用途有两类:
- 工厂方法
- 工具方法
工厂方法
js
class Article {
constructor(title, date) {
this.title = title
this.date = date
}
static createToday(title) {
return new Article(title, new Date())
}
}
const article = Article.createToday('news')工具方法
js
class Article {
constructor(title, views) {
this.title = title
this.views = views
}
static compare(a, b) {
return a.views - b.views
}
}这种方法逻辑上属于 Article 这个类型,但不依赖某个具体实例。
静态属性适合做什么
静态属性适合放“类级别共享数据”:
js
class Config {
static version = '1.0.0'
static defaultTimeout = 3000
}
console.log(Config.version)如果某个值应该是每个实例各自拥有,就不应该写成静态属性。
和实例属性 / 实例方法的区别
可以这样理解:
- 实例属性和实例方法,描述“某个对象自身”的状态与行为。
- 静态属性和静态方法,描述“这个类整体”的状态与行为。
js
class User {
static role = 'member'
constructor(name) {
this.name = name
}
sayHi() {
return `hi, ${this.name}`
}
}这里:
role属于Username和sayHi()属于实例
静态成员也可以被继承
子类不仅继承实例方法,也会继承父类的静态成员:
js
class Animal {
static category = 'creature'
static create() {
return new this()
}
}
class Rabbit extends Animal {}
console.log(Rabbit.category) // 'creature'
const rabbit = Rabbit.create()
console.log(rabbit instanceof Rabbit) // true这里 Rabbit 可以直接访问父类的静态成员。
static 和 this 的关系
在静态方法里,this 指向当前类本身:
js
class Animal {
static create() {
return new this()
}
}
class Rabbit extends Animal {}
const rabbit = Rabbit.create()这一点在写工厂方法时很有用,因为它能让子类直接复用父类静态逻辑。
从技术上看等价于给类本身赋值
下面两种写法本质上是同一类事情:
js
class User {
static type = 'user'
static createGuest() {}
}js
class User {}
User.type = 'user'
User.createGuest = function () {}只是 static 写法更集中,也更符合类语义。
使用建议
- 和实例无关的辅助逻辑,优先考虑静态方法。
- 需要返回某种默认实例时,可以用静态工厂方法。
- 不要把本该属于实例的数据误写成静态属性。
- 看到一个方法里完全不依赖实例状态时,可以想一想它是否更适合写成静态方法。
