JavaScript 类(class):从零开始掌握面向对象编程
在学习 JavaScript 的过程中,你可能已经接触过函数、对象、数组这些基础概念。但当你开始构建更复杂的项目时,会发现代码越来越难维护,变量和逻辑混杂在一起,难以扩展。这时候,“JavaScript 类(class)” 就成了你提升代码结构化的关键工具。
类,就像是一个模板或蓝图,用来创建具有相同属性和方法的对象。它让代码更清晰、更可复用,也更符合现实世界中的“事物”建模方式。比如,你可以定义一个“汽车”类,然后根据这个类生成多辆具体的汽车实例,每辆车都有自己的颜色、速度,但共享相同的驾驶逻辑。
本文将带你一步步理解 JavaScript 类的语法、特性与最佳实践,无论你是初学者还是有一定经验的开发者,都能从中获得实用价值。
类的定义与基本语法
在 ES6(ECMAScript 2015)中,JavaScript 引入了 class 关键字,正式支持面向对象编程。虽然 JavaScript 本身是基于原型的语言,但 class 提供了一种更直观、更接近其他语言(如 Java、C++)的写法。
class Car {
// 构造函数,用于初始化新实例
constructor(brand, color) {
this.brand = brand; // 实例属性:品牌
this.color = color; // 实例属性:颜色
this.speed = 0; // 默认速度为 0
}
// 实例方法:启动引擎
startEngine() {
console.log(`${this.brand} 的引擎已启动!`);
}
// 实例方法:加速
accelerate() {
this.speed += 10;
console.log(`当前速度:${this.speed} km/h`);
}
// 实例方法:停车
stop() {
this.speed = 0;
console.log(`${this.brand} 已停车。`);
}
}
重要说明:
class Car声明了一个名为Car的类。constructor是类的构造函数,当使用new创建实例时自动调用。this指向当前实例对象,用于访问实例属性和方法。- 所有方法都定义在类的原型上,共享使用,节省内存。
创建实例与调用方法
类本身只是一个蓝图,真正要使用它,需要通过 new 关键字创建实例。
// 创建两辆不同的汽车
const myCar = new Car("丰田", "红色");
const yourCar = new Car("本田", "蓝色");
// 调用实例方法
myCar.startEngine(); // 输出:丰田 的引擎已启动!
myCar.accelerate(); // 输出:当前速度:10 km/h
myCar.accelerate(); // 输出:当前速度:20 km/h
myCar.stop(); // 输出:丰田 已停车。
// 每个实例都有独立的状态
console.log(myCar.color); // 输出:红色
console.log(yourCar.color); // 输出:蓝色
形象比喻:
类就像“汽车制造图纸”,而实例就是“实际生产出来的汽车”。你可以根据同一张图纸生产出无数辆不同的车,每辆都有自己的颜色、车牌和行驶记录,但都遵循相同的设计逻辑。
属性与方法的访问控制
JavaScript 类默认没有真正的私有属性,但可以通过命名约定来暗示私有性。ES2022 引入了 # 符号,真正支持私有字段。
class BankAccount {
// 公共属性
accountHolder;
// 私有字段(只能在类内部访问)
#balance = 0;
#pin;
constructor(holder, pin) {
this.accountHolder = holder;
this.#pin = pin;
}
// 公共方法:存款
deposit(amount) {
if (amount > 0) {
this.#balance += amount;
console.log(`存款成功!当前余额:${this.#balance} 元`);
} else {
console.log("存款金额必须大于 0");
}
}
// 公共方法:取款
withdraw(amount, pin) {
if (pin !== this.#pin) {
console.log("密码错误!");
return;
}
if (amount > this.#balance) {
console.log("余额不足!");
return;
}
this.#balance -= amount;
console.log(`取款成功!当前余额:${this.#balance} 元`);
}
// 公共方法:查看余额(只读)
getBalance() {
return this.#balance;
}
}
// 使用示例
const account = new BankAccount("张三", "1234");
account.deposit(1000); // 存款成功!当前余额:1000 元
account.withdraw(300, "1234"); // 取款成功!当前余额:700 元
console.log(account.getBalance()); // 输出:700
// console.log(account.#balance); // 报错!无法访问私有字段
注意:
#balance是私有字段,外部无法直接访问。- 私有字段必须在类内部定义和使用。
- 这种机制增强了封装性,防止数据被意外修改。
继承与扩展:构建类的层次结构
现实世界中,很多事物具有“继承”关系。比如“电动车”是“汽车”的一种。在 JavaScript 中,可以使用 extends 关键字实现继承。
// 父类:汽车
class Car {
constructor(brand, color) {
this.brand = brand;
this.color = color;
this.speed = 0;
}
startEngine() {
console.log(`${this.brand} 的引擎已启动!`);
}
accelerate() {
this.speed += 10;
console.log(`当前速度:${this.speed} km/h`);
}
}
// 子类:电动车(继承 Car)
class ElectricCar extends Car {
constructor(brand, color, batteryLevel) {
// 调用父类构造函数
super(brand, color);
this.batteryLevel = batteryLevel; // 新增属性
}
// 重写父类方法
startEngine() {
console.log(`${this.brand} 的电动马达启动了!`);
console.log(`电池电量:${this.batteryLevel}%`);
}
// 新增方法:充电
charge(percent) {
this.batteryLevel += percent;
if (this.batteryLevel > 100) this.batteryLevel = 100;
console.log(`充电完成!当前电量:${this.batteryLevel}%`);
}
}
// 使用
const tesla = new ElectricCar("特斯拉", "白色", 80);
tesla.startEngine(); // 输出:特斯拉 的电动马达启动了!电池电量:80%
tesla.accelerate(); // 输出:当前速度:10 km/h
tesla.charge(20); // 输出:充电完成!当前电量:100%
关键点:
extends Car表示ElectricCar继承自Car。super(...)必须在子类构造函数中第一行调用,用于初始化父类。- 子类可以重写父类的方法,实现多态。
- 子类可以添加新的属性和方法,扩展功能。
静态方法与属性:属于类,而非实例
有时候,我们希望某些方法或属性属于类本身,而不是每个实例。这时就可以使用 static。
class MathUtils {
// 静态方法:计算两个数的最大值
static max(a, b) {
return a > b ? a : b;
}
// 静态属性:数学常数 π
static PI = 3.14159265359;
// 静态方法:判断是否为偶数
static isEven(num) {
return num % 2 === 0;
}
}
// 使用静态方法,无需创建实例
console.log(MathUtils.max(10, 20)); // 输出:20
console.log(MathUtils.PI); // 输出:3.14159265359
console.log(MathUtils.isEven(8)); // 输出:true
适用场景:
- 工具类方法(如日期格式化、字符串处理)。
- 常量定义(如
PI、E)。- 工厂方法(如
Person.createEmployee())。
类的最佳实践与常见误区
在实际开发中,合理使用 JavaScript 类(class) 能极大提升代码质量。以下是一些建议:
| 建议 | 说明 |
|---|---|
| 避免过度封装 | 不要为了“类”而类,简单对象可以直接用字面量。 |
| 合理使用继承 | 继承层级不宜过深,优先使用组合(Composition)替代继承。 |
| 使用私有字段 | 尽量用 # 定义私有属性,增强数据安全性。 |
| 方法命名清晰 | 使用动词开头(如 startEngine、calculateTotal),避免模糊命名。 |
| 避免在类中写复杂逻辑 | 保持类职责单一,复杂逻辑应拆分到独立函数或模块。 |
结语
JavaScript 类(class) 是现代 JavaScript 开发中不可或缺的一部分。它不仅让代码结构更清晰,还提升了可维护性和可扩展性。从创建实例、方法调用,到继承、私有字段、静态成员,每一步都为你构建更健壮的应用打下基础。
无论你是正在学习前端框架(如 Vue 3.0、React 18),还是开发 Node.js 后端服务,理解类的原理和用法,都将让你的代码更加专业、规范。
掌握 JavaScript 类(class),不只是学习语法,更是掌握一种思维方式:将现实世界的问题,抽象为可复用、可扩展的代码模块。这正是编程的魅力所在。