Skip to content

class 基本使用

class 用来描述“一类对象的公共结构和行为”。它让构造函数、原型方法、继承这些能力写起来更直观。

class 解决什么问题

更直接地说,class 适合表达:

  • 一组实例共享的数据结构
  • 一组实例共享的方法
  • 明确的类型层级关系
js
class User {
  constructor(name) {
    this.name = name
  }

  sayHi() {
    console.log(`hi, ${this.name}`)
  }
}

一个类最常见的组成

类里通常会出现这些成员:

  • constructor
  • 原型方法
  • getter / setter
  • 实例字段
  • 静态成员
js
class User {
  role = 'guest'

  constructor(name) {
    this.name = name
  }

  sayHi() {
    console.log(`hi, ${this.name}`)
  }

  get label() {
    return `${this.role}:${this.name}`
  }
}

constructor

constructor 是实例初始化入口,在 new 时自动执行:

js
class User {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
}

const user = new User('Lee', 18)

如果类里没有显式写 constructor,JavaScript 会提供一个默认空构造器。

方法默认放在原型上

类里声明的方法不会复制到每个实例上,而是放在原型上共享:

js
class User {
  sayHi() {
    console.log('hi')
  }
}

const u1 = new User()
const u2 = new User()

console.log(u1.sayHi === u2.sayHi) // true

这也是类适合描述“多实例共享行为”的原因。

实例字段

类中直接声明的字段会出现在实例本身上:

js
class User {
  role = 'guest'
}

const user = new User()
console.log(user.role) // 'guest'

实例字段和原型方法不是一回事:

  • 字段在实例上
  • 方法通常在原型上

getter 和 setter

如果属性读取或写入时需要额外逻辑,可以用访问器:

js
class User {
  constructor(name) {
    this.name = name
  }

  get name() {
    return this._name
  }

  set name(value) {
    if (value.length < 2) {
      throw new Error('name is too short')
    }

    this._name = value
  }
}

这适合把校验、格式整理、只读封装等逻辑收进属性访问过程。

计算属性名

类方法也支持计算属性名:

js
const methodName = 'sayHi'

class User {
  [methodName]() {
    console.log('hi')
  }
}

这种写法存在,但日常业务里通常不如显式方法名直观。

类表达式

类也可以像函数一样写成表达式:

js
const User = class {
  sayHi() {
    console.log('hi')
  }
}

这在“工厂函数返回类”或“按条件生成类”时偶尔会见到。

class 和构造函数的关系

class 并不是完全独立的新对象模型,本质上仍然建立在构造函数和原型机制之上。

js
class User {
  sayHi() {}
}

console.log(typeof User) // 'function'
console.log(typeof User.prototype.sayHi) // 'function'

只是 class 把原来分散写在构造函数、prototype、继承链上的内容收成了一种更稳定的语法结构。

class 和普通函数不完全一样

虽然类本质上和函数有关,但它有自己的语法限制:

  • 类必须通过 new 调用
  • 类方法默认不可枚举
  • 类体内代码默认是严格模式
js
class User {}

// User() // TypeError
const user = new User()

方法里的 this

类方法里的 this 仍然取决于调用方式,不会因为写在 class 里就自动绑定:

js
class Button {
  constructor(text) {
    this.text = text
  }

  click() {
    console.log(this.text)
  }
}

const button = new Button('ok')
setTimeout(button.click, 1000) // undefined

如果方法会被单独传递,通常要手动处理绑定问题,或改成实例字段箭头函数。

什么时候适合用 class

更适合:

  • 需要批量创建同类实例
  • 有清晰的实例方法和状态
  • 需要继承或面向对象建模

如果只是组织几个工具函数,通常不需要强行上 class

使用建议

  • 先把 class 理解成“组织构造函数和原型的一种更清晰写法”。
  • 类方法放共享行为,实例字段放实例状态。
  • 不要因为能用 class,就把所有逻辑都包成类。
  • 看到类方法丢失 this 时,先检查调用方式,而不是以为 class 自带绑定。

基于 MIT 许可发布