1. 从原型链到 class:JavaScript 面向对象编程的进化
作为一位经历过 ES5 时代的前端开发者,我至今还记得第一次用原型链实现继承时踩过的坑。那些年我们不得不手动维护 prototype 和 constructor 的关系,稍不注意就会遇到原型链断裂或者 constructor 指向错误的问题。直到 ES6 的 class 出现,才让 JavaScript 的面向对象编程变得优雅起来。
class 并不是 JavaScript 引入的全新面向对象模型,它本质上只是 ES5 构造函数和原型继承的语法糖。这个设计非常明智——既保留了 JavaScript 基于原型的特性,又提供了更符合主流编程习惯的语法。在实际项目中,class 的引入显著降低了团队协作的认知成本,特别是对那些有 Java 或 C++ 背景的开发者。
重要提示:虽然 class 让语法更简洁,但理解其背后的原型机制仍然至关重要。这是区分初级和高级 JavaScript 开发者的关键知识点之一。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. class 基础语法深度解析
2.1 从构造函数到 class 的转变
让我们从一个具体的例子开始,对比 ES5 构造函数和 ES6 class 的写法差异。假设我们要创建一个表示二维点的类:
javascript复制// ES5 构造函数写法
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function() {
return `(${this.x}, ${this.y})`;
};
Point.distance = function(p1, p2) {
const dx = p1.x - p2.x;
const dy = p1.y - p2.y;
return Math.sqrt(dx * dx + dy * dy);
};
同样的功能用 ES6 class 实现:
javascript复制class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return `(${this.x}, ${this.y})`;
}
static distance(p1, p2) {
const dx = p1.x - p2.x;
const dy = p1.y - p2.y;
return Math.sqrt(dx * dx + dy * dy);
}
}
从代码量来看,两者差别不大,但 class 语法将相关的属性和方法组织在了一起,结构更加清晰。特别是静态方法的定义,class 使用 static 关键字使其意图更加明确。
2.2 class 的核心特性与注意事项
在实际使用 class 时,有几个关键特性需要特别注意:
- 必须使用 new 调用:与 ES5 构造函数不同,class 不能作为普通函数调用,否则会抛出错误。这是为了避免意外污染全局作用域。
javascript复制const p = Point(1, 2); // TypeError: Class constructor Point cannot be invoked without 'new'
- 不存在变量提升:class 声明不会像 function 声明那样被提升,存在暂时性死区。
javascript复制new Person(); // ReferenceError: Cannot access 'Person' before initialization
class Person {}
-
自动严格模式:class 内部默认启用严格模式,这意味着一些松散模式下允许的操作会被禁止。
-
