🚀 ES6 class 与 JavaScript 的 OOP 区别
欢迎来到我的博客文章!所有文章都是满满的前端干货,文章简明扼要。
ES6 的 class 并不是"与 JavaScript 的 OOP 不同",它本身就是 JavaScript 实现面向对象编程(OOP)的一种方式。更准确地说,ES6 class 是对 JavaScript 原有基于原型(Prototype-Based)的 OOP 模型的语法封装,并没有改变其底层机制。
一、本质:同一套 OOP 模型,两种写法
| 特性 | ES6 class | 传统原型写法(ES5) |
| 底层机制 | 基于原型链(Prototype Chain) | 基于原型链(Prototype Chain) |
| 是否改变 OOP 模型 | ❌ 否(只是语法糖) | ✅ 原生实现 |
| 可互操作性 | 完全兼容,可混合使用 | 完全兼容 |
🌰 等价代码示例
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a sound`);
}
}
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a sound`);
};
两者生成的对象完全相同:
const dog1 = new Animal("Dog"); // 无论用哪种定义方式
console.log(dog1.__proto__ === Animal.prototype); // true
二、主要区别(语法与体验层面)
| 维度 | ES6 class | 传统原型写法 |
| 1. 语法简洁性 | ✅ 更清晰,接近 Java/C# | ❌ 繁琐,需手动操作 prototype |
| 2. 构造函数调用 | 必须用 new,否则报错 | 可不用 new(但会污染全局) |
| 3. 方法枚举性 | 方法默认 enumerable: false | 手动添加的方法默认 enumerable: true |
| 4. 提升(Hoisting) | ❌ class 声明不会被提升 | ✅ 函数声明会被提升 |
| 5. 静态方法 | static methodName() {} | Constructor.methodName = function() {} |
| 6. 继承写法 | extends + super() | 需手动设置原型链(Object.create + call) |
| 7. 私有字段 | 支持 #field(ES2022+) | 无真正私有(常用 _field 约定) |
🔍 继承写法对比
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
bark() {
console.log("Woof!");
}
}
function Dog(name, breed) {
Animal.call(this, name);
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
console.log("Woof!");
};
三、prototype 与 __proto__ 的区别
1. prototype:构造函数的"模板"
只有函数才有 prototype 属性(箭头函数除外)。当使用 new Fn() 创建实例时,实例的 __proto__ 会自动指向 Fn.prototype。
2. __proto__:对象的"原型链接"
所有对象(包括数组、函数、普通对象)都有 __proto__。它指向创建该对象的构造函数的 prototype。
四、常见误解澄清
❌ 误解 1:"ES6 class 让 JS 变成了类式语言"
事实:JS 仍然是基于原型的语言。class 只是语法糖,typeof class 返回 "function"。
❌ 误解 2:"用 class 就不需要懂原型了"
事实:调试、高级库开发、面试题(如手写继承)仍需深入理解原型链。
❌ 误解 3:"class 和 function 构造器完全不同"
事实:class 编译后就是构造函数 + 原型方法。
原型链示例:
eagle→ __proto__ → Dog.prototype
→ __proto__ → Animal.prototype
→ __proto__ → Object.prototype
→ __proto__ → null