主题
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自带绑定。
