JavaScript 的“类继承”本质是原型链继承,ES6 class 仅为语法糖,底层仍依赖函数与原型对象的连接关系。

“类继承”在 JavaScript 中看似像 Java 或 C++ 那样靠“类”实现,其实底层根本没有真正的类。ES6 的 class 只是语法糖,背后依然是函数 + 原型链。所谓“类继承”,本质就是让子类实例的 __proto__ 一层层往上连到父类的原型对象,最终形成一条可查找的链路。
“类”不是类,而是构造函数的包装
当你写 class Parent {},JS 引擎实际把它转成一个带 prototype 属性的函数;extends 并不是创建类型关系,而是手动设置子类的 prototype.__proto__ 指向父类的 prototype。
-
class Parent {}→ 等价于function Parent() {},且Parent.prototype自动存在 -
class Child extends Parent {}→ 实际做了两件事:
① 让Child.prototype.__proto__ === Parent.prototype
② 让Child.__proto__ === Parent(静态方法继承)
实例方法靠原型链逐级查找
你调用 child.sayHello(),JS 不是在 child 对象上直接找方法,而是按顺序查:
- 先看
child自身有没有sayHello - 没有?去
child.__proto__(即Child.prototype)找 - 还没?继续去
Child.prototype.__proto__(即Parent.prototype)找 - 再没?一路找到
Object.prototype,最后到null
这个“一级一级往上翻”的过程,就是原型链在工作——它不靠编译时的类型声明,而靠运行时的属性访问规则。
继承的实质是原型对象的复用与连接
真正被“继承”的,不是代码拷贝,而是共享引用:
- 所有
new Child()实例,其__proto__都指向同一个Child.prototype - 而
Child.prototype又通过__proto__连到Parent.prototype - 所以父类定义在
Parent.prototype上的方法,所有子类实例都能访问,且只存一份
这和传统面向对象语言中“子类复制父类结构”完全不同——JS 是动态链接,靠的是对象间隐式关联的原型指针。
ES6 class 没改变底层机制,只统一了写法
不用 class 也能实现完全一样的继承效果,比如:
function Parent(name) { this.name = name; }
Parent.prototype.eat = function() { console.log('eating'); };
function Child(name, age) {
Parent.call(this, name); // 继承实例属性
}
Child.prototype = Object.create(Parent.prototype); // 手动连原型链
Child.prototype.constructor = Child;
Child.prototype.play = function() { console.log('playing'); };
这段 ES5 代码和 class Child extends Parent 效果一致:实例能调 eat 和 play,原型链结构也完全相同。区别只是写法更繁琐,而非机制不同。

















