JavaScript面向对象编程存在争议,核心在于其基于原型的继承机制与ES6引入的class语法糖之间的表里不一;class提升可读性与工具链兼容性但易掩盖原型动态性,原型操作更底层灵活却易出错;选择应依团队、场景及维护成本而定。

JavaScript的面向对象编程有争议,核心在于它没有传统意义上的“类”,而是基于原型(prototype)的继承机制;后来引入的class语法只是语法糖,并不改变底层逻辑。这种“表里不一”的设计,让开发者在理解、调试和协作时容易产生分歧:有人觉得class更清晰易读,有人坚持用原型才能真正掌握JS本质。
class语法:写起来像Java,但运行时还是原型
class关键字从ES6开始支持,看起来和Java、C++很像,支持constructor、static、extends、super等特性。但它只是对原型链操作的封装——编译后仍是函数+原型赋值。比如:
class Person {
constructor(name) { this.name = name; }
say() { return `Hi, I'm ${this.name}`; }
}
const p = new Person('Alice');
// 实际上 p.__proto__ === Person.prototype
好处是结构清晰、继承写法统一、配合TypeScript类型推导友好;缺点是容易误以为JS有了“真正的类”,忽略原型动态性,比如修改Person.prototype仍会影响已有实例。
立即学习“Java免费学习笔记(深入)”;
原型继承:更底层,也更灵活
直接操作prototype或使用Object.create()构建对象关系,能精确控制委托链。适合需要高度定制继承行为、实现轻量级对象工厂,或深入理解JS执行模型的场景。
- 用
Object.create(Animal.prototype)手动指定原型,比extends更透明 - 可以给单个对象设置原型,不依赖构造函数
- 运行时可动态增删原型方法,适合插件化或热更新逻辑
但手写容易出错,比如忘记调用Parent.call(this)导致属性丢失,或者混淆this绑定。
怎么选?看团队、场景和长期维护成本
没有绝对优劣,关键看实际约束:
- 新项目、中大型团队、需对接TypeScript/React/Vue生态 → 优先用
class,降低认知门槛,工具链支持好 - 写库、做框架、性能敏感或需精细控制原型链 → 直接操作原型更可控,比如Lodash的
_.create或Redux的store增强器 - 维护老代码(ES5为主)或面试考察原理 → 必须懂
prototype、__proto__、new执行过程
混用也可以:用class组织主逻辑,内部关键路径用Object.setPrototypeOf()或Object.assign()微调行为。
基本上就这些。class不是“错的抽象”,原型也不是“过时的古董”——它们是同一套机制的不同表达。真正的问题不在语法,而在是否清楚自己写的每一行,最终落在哪条原型链上。











