🔍 从函数到类:JavaScript 的进化之路
在 ES6 之前,JavaScript 通过构造函数 + 原型链模拟面向对象编程:
function Person(name) {
this.name = name;
}
Person.prototype.sayHi = function() {
console.log(`Hi, I'm ${this.name}`);
};
这种方式虽然可行,但写法繁琐、可读性差,且缺乏真正的封装能力。
ES6 引入了 class 关键字,让面向对象编程变得更直观、更安全、更贴近其他主流语言(如 Java、C#)。
⚠️ 注意:
class并不是“新类型”,它本质上仍是基于原型的语法糖,但它带来了语义化、封装性和开发体验的巨大提升。
✨ ES6 Class 的核心组成部分
一个完整的 ES6 类通常包含以下要素(参考下图结构):
1. constructor 构造器
- 类的初始化入口;
- 自动调用,用于设置实例属性;
- 每个类最多只能有一个
constructor。
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
2. 实例方法(Instance Methods)
- 定义在类体中的普通方法;
- 自动绑定到原型(
User.prototype)上; - 所有实例共享这些方法,节省内存。
class User {
sayHello() {
console.log(`Hello, ${this.name}!`);
}
}
3. 私有属性(Private Fields)—— ES2022+
使用 # 前缀定义真正私有的属性或方法,外部无法访问,也无法被枚举。
class Counter {
#count = 0; // 私有属性
increment() {
this.#count++;
}
getCount() {
return this.#count; // 只能通过内部方法暴露
}
}
const c = new Counter();
// c.#count; // ❌ SyntaxError: Private field '#count' must be declared in an enclosing class
✅ 私有字段是强封装的关键,避免外部随意修改内部状态。
4. Getter / Setter —— 属性访问器
通过 get 和 set 控制对属性的读写逻辑,实现“计算属性”或“数据校验”。
class Rectangle {
constructor(width, height) {
this._width = width;
this._height = height;
}
get area() {
return this._width * this._height;
}
set width(value) {
if (value <= 0) throw new Error('Width must be positive');
this._width = value;
}
}
const rect = new Rectangle(5, 4);
console.log(rect.area); // 20(像读属性一样调用)
rect.width = 10; // 触发 setter 校验
💡
get方法让方法调用看起来像访问属性,提升 API 的自然感。
🛡️ 封装与安全性:为什么私有字段很重要?
在没有私有字段的时代,开发者常用 _ 下划线约定表示“内部属性”(如 _count),但这只是弱约定,外部依然可以随意访问和修改:
// 不安全的“伪私有”
class BadCounter {
constructor() {
this._count = 0;
}
}
const bad = new BadCounter();
bad._count = -999; // ❌ 轻易破坏内部状态!
而 #count 是语言级别的私有,引擎会阻止任何外部访问,从根本上保障封装性。
📌 总结:ES6 Class 的核心价值
| 特性 | 作用 | 优势 |
|---|---|---|
constructor | 初始化实例 | 统一入口,逻辑清晰 |
| 实例方法 | 定义行为 | 自动挂载原型,内存高效 |
#privateField | 私有属性/方法 | 真正封装,防止外部篡改 |
get / set | 属性访问控制 | 支持校验、计算、懒加载 |
🌟 Class 不是替代原型,而是对原型模式的优雅封装。它让我们写出:
- 更易读的代码;
- 更安全的封装;
- 更符合工程规范的结构。
💡 最佳实践建议
- 优先使用
#定义内部状态,不要依赖_约定; - 用
get暴露只读计算属性(如size、area); - 避免在构造器中做复杂逻辑,保持轻量;
- 方法尽量定义在类体内,而非手动挂到
prototype上。
📚 结语
ES6 的 class 不仅让 JavaScript 的面向对象编程更“像样”,更重要的是——它推动了整个前端工程化的进步。从 React 组件到数据结构封装,class 已成为现代 JS 开发不可或缺的一部分。
掌握它的每一个细节,就是掌握编写健壮、可维护、专业级代码的第一步。