javascript继承本质是原型链委托而非类复制,对象通过__proto__链动态查找属性方法,es6 class仅为语法糖,核心仍是运行时委托、实例属性与原型方法分离、无编译期类型约束的轻量模型。

JavaScript 的继承模型不是“复制父类”,而是“链接到父类的原型”。这是它和 Java、C++ 等经典 OOP 语言最根本的区别。
继承的本质不同:链接 vs 复制
经典 OOP(如 C++、Java)中,子类在编译或定义时就拷贝了父类的属性和方法结构,形成独立的类型体系;而 JavaScript 中没有真正的“类”实体,只有对象和原型。子类实例通过原型链向上查找属性和方法——查不到就顺着 __proto__ 找父类原型,再找不到就找 Object.prototype,最后到 null 结束。这个过程是动态的、运行时的、只读的委托关系。
没有真正的类,只有构造函数与原型对象
ES6 的 class 是语法糖,背后仍是基于函数和 prototype 的机制:
-
class A {}实际生成的是一个不可枚举的构造函数,其A.prototype存放共享方法 -
extends并不创建新类结构,而是让子类的prototype指向父类原型的副本(内部用Object.setPrototypeOf(Child.prototype, Parent.prototype)或类似逻辑) - 所有“继承”行为最终都依赖
[[Prototype]]链,而非类型系统或编译期检查
实例属性与共享方法的分离更明显
在经典 OOP 中,字段和方法通常统一声明在类体中;JavaScript 则天然区分:
- 在构造函数内用
this.xxx = ...定义的,是每个实例独享的属性(包括引用类型) - 在
Constructor.prototype.xxx = function(){}上定义的,是所有实例共享的方法,节省内存但不可修改(除非直接改原型) - 这种分离让开发者必须主动思考“什么该私有,什么该复用”,也导致组合继承等模式成为必要
缺乏访问控制与类型约束
经典语言有 private、protected、接口、抽象类等机制来规范继承边界;JavaScript 直到近年才通过 #field 私有字段提供有限封装,且无编译期类型校验:
- 子类可以随意覆盖父类任何方法,哪怕语义不兼容
- 无法强制子类实现某个方法(没有原生 interface 或 abstract class)
- 多态靠鸭子类型:只要对象有某个方法,就能被当作某类使用,不依赖继承关系本身
理解这点,才能避免把 Java 的继承思维硬套进 JS——不是“Dog 是 Animal 的一种”,而是“Dog 实例在需要时能顺着原型链找到 Animal 定义的行为”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











