javascript继承基于原型链委托而非类复制,通过__proto__链接对象实现属性方法访问;class是语法糖,底层仍操作原型;寄生组合继承和class+extends为推荐方案。

JavaScript 的继承不是靠“类与类之间复制”,而是靠对象间建立委托关系——一个对象通过 __proto__ 链接到另一个对象,从而能访问后者身上的属性和方法。这个链条就是原型链,它是整个 JS 面向对象机制的底层支柱。
原型链是继承的物理基础
每个函数都有 prototype 属性,它是一个对象,初始包含 constructor 指向自身;每个由该函数创建的实例,其内部 [[Prototype]](通常可通过 __proto__ 访问)会自动指向该函数的 prototype。
- 当你写
const p = new Person(),p.__proto__ === Person.prototype为真 - 访问
p.sayHi()时,引擎先查p自身,没找到就顺着__proto__找到Person.prototype上的方法 - 若
Person.prototype也没定义,继续向上查Person.prototype.__proto__(即Object.prototype),最终到null终止
class 只是语法糖,本质仍是原型操作
ES6 的 class 看似像 Java,但编译后仍是函数 + 原型赋值。比如:
-
class Child extends Parent底层会设置Child.__proto__ = Parent(静态继承) - 同时设置
Child.prototype.__proto__ = Parent.prototype(实例方法继承) -
super()在构造函数中实际调用的是Parent.call(this, ...),确保父类实例属性正确挂载
常见继承方式的关键差异点
不同实现方案解决的问题不同,选错会导致隐蔽 bug:
-
原型链继承:子类
prototype = new Parent()→ 方法可复用,但引用类型(如数组、对象)被所有实例共享 -
构造函数继承:在子类中
Parent.call(this, ...)→ 实例属性隔离,但父类原型方法无法继承 -
寄生组合继承(推荐 ES5 方案):用
Object.create(Parent.prototype)设置子类原型,再手动绑定constructor,兼顾属性隔离与方法复用 -
class + extends(推荐现代方案):语义清晰、支持
super、静态方法、getter/setter,且浏览器兼容性已无顾虑
实战中必须注意的细节
写继承代码时,这几个点最容易出错:
- 手动设置原型后,记得修正
constructor,否则instance.constructor会指向父类 - 用
instanceof判断类型时,依赖的是原型链上是否存在对应构造函数的prototype - 避免在父类构造函数中初始化引用类型作为实例属性,除非你明确需要共享
- ES6 class 中,子类构造函数必须第一行调用
super(),否则this不可用——这是引擎强制保障原型链初始化的机制
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











