javaScript继承通过原型链和class实现,原型链继承共享引用导致问题,组合继承解决属性独立与方法复用,class语法更简洁但基于原型,寄生组合继承最优。

javascript 实现继承的方式主要依赖于原型链和 es6 引入的 class 语法。虽然 class 看起来像传统面向对象语言的类继承,但底层依然基于原型机制。下面详细说明两种方式的实现原理与使用方法。
原型链继承:通过 prototype 实现
JavaScript 中每个函数都有一个 prototype 属性,指向一个对象,该对象包含可以被实例共享的属性和方法。通过将子构造函数的原型指向父构造函数的实例,可以实现继承。
注意:这种方式无法向父类构造函数传参,且所有实例共享引用类型属性。
基本实现:
function Parent() { this.name = 'parent'; this.colors = ['red', 'blue']; } Parent.prototype.getName = function() { return this.name; }; function Child() { this.type = 'child'; } // 继承父类 Child.prototype = new Parent(); const c1 = new Child(); c1.colors.push('green'); const c2 = new Child(); console.log(c2.colors); // ['red', 'blue', 'green'] —— 共享问题
这种写法的问题在于,所有 Child 实例共享同一个 Parent 实例,导致引用类型数据被共用。
立即学习“Java免费学习笔记(深入)”;
组合继承:构造函数 + 原型链
为解决原型链继承的问题,常用“组合继承”:在子类构造函数中调用父类构造函数,并结合原型链。
实现方式:
function Parent(name) { this.name = name; this.colors = ['red', 'blue']; } Parent.prototype.getName = function() { return this.name; }; function Child(name, age) { // 调用父类构造函数 Parent.call(this, name); this.age = age; } // 建立原型链 Child.prototype = Object.create(Parent.prototype); Child.prototype.constructor = Child; const c1 = new Child('Tom', 12); c1.colors.push('green'); const c2 = new Child('Jerry', 10); console.log(c1.getName()); // 'Tom' console.log(c2.colors); // ['red', 'blue'] —— 不受影响
这样既保证了实例属性独立,又实现了方法复用,是较为推荐的传统继承方式。
ES6 Class 继承:更清晰的语法糖
ES6 引入了 class 和 extends 关键字,让继承写法更直观,但本质仍是基于原型。
使用示例:
class Parent { constructor(name) { this.name = name; this.colors = ['red', 'blue']; } getName() { return this.name; } } class Child extends Parent { constructor(name, age) { super(name); // 必须调用 super() this.age = age; } getAge() { return this.age; } } const c1 = new Child('Alice', 15); c1.colors.push('yellow'); const c2 = new Child('Bob', 14); console.log(c1.getName()); // 'Alice' console.log(c2.colors); // ['red', 'blue'] —— 独立
class 继承自动处理原型链连接,super() 调用父类构造函数,语法简洁且不易出错。
Object.create 与寄生组合继承
最优化的传统继承模式是“寄生组合继承”,它避免了组合继承中父类构造函数被调用两次的问题。
手动实现:
function inheritPrototype(Child, Parent) { const proto = Object.create(Parent.prototype); proto.constructor = Child; Child.prototype = proto; } function Parent(name) { this.name = name; } function Child(name, age) { Parent.call(this, name); this.age = age; } inheritPrototype(Child, Parent); Child.prototype.getAge = function() { return this.age; };
这种方式高效且语义清晰,是许多库内部实现继承的方法。
基本上就这些。理解原型链是掌握 JavaScript 继承的关键,而 class 则提供了更友好的封装。无论使用哪种方式,核心逻辑都围绕着原型查找机制展开。