Skip to content

静态属性和静态方法

静态成员属于类本身,而不属于某个实例。它适合表达“整个类共享的能力”或“和实例无关的辅助能力”。

什么是静态成员

class 中,使用 static 声明的属性和方法就是静态成员:

js
class User {
  static type = 'user'

  static createGuest() {
    return new User('Guest')
  }

  constructor(name) {
    this.name = name
  }
}

这里的 typecreateGuest() 都挂在 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 属于 User
  • namesayHi() 属于实例

静态成员也可以被继承

子类不仅继承实例方法,也会继承父类的静态成员:

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 可以直接访问父类的静态成员。

staticthis 的关系

在静态方法里,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 写法更集中,也更符合类语义。

使用建议

  • 和实例无关的辅助逻辑,优先考虑静态方法。
  • 需要返回某种默认实例时,可以用静态工厂方法。
  • 不要把本该属于实例的数据误写成静态属性。
  • 看到一个方法里完全不依赖实例状态时,可以想一想它是否更适合写成静态方法。

基于 MIT 许可发布