本文介绍了JavaScript中六种主要的继承实现方式及其适用场景,并推荐在现代项目中优先使用ES6的class继承,每种继承方式都有其特点和适用范围,选择合适的继承方式对于编写清晰、高效的JavaScript代码至关重要,感兴趣的朋友一起看看吧 继承方式 适用场景 现代选择优先级 原型链继承快速实现简单原型链(已过时)⭐️构造函数继承需要独立实例属性的场景⭐️⭐️组合继承传统项目兼容性解决方案⭐️⭐️寄生组合式继承需要高效且标准的继承方案⭐️⭐️⭐️⭐️ES6 class 继承现代项目开发(Babel转译后兼容性好)⭐️⭐️⭐️⭐️⭐️
4️⃣原型式/寄生式继承主要用于对象克隆而非类继承场景
目录
一、原型链继承二、构造函数继承三、组合继承(经典继承)四、原型式继承五、寄生式继承六、寄生组合式继承(最优解)七、ES6class继承总结与场景对比在 JavaScript 中,继承的实现方式主要有以下几种,每种方式适用于不同的场景:
一、原型链继承
实现方式:
function Parent() { this.name = 'Parent'; }Parent.prototype.say = function() { return this.name; };function Child() {}Child.prototype = new Parent(); // 原型继承关键const child = new Child();child.say(); // 输出 "Parent"
特点:
子类实例通过原型链访问父类属性和方法问题:父类的引用类型属性会被所有子类实例共享场景:
简单继承结构,无引用类型共享问题需求的场景老项目快速实现继承(现代开发不推荐优先使用)二、构造函数继承
实现方式:
function Parent(name) { this.name = name; }function Child(name) { Parent.call(this, name); // 构造函数继承关键}const child = new Child('Child');child.name; // 输出 "Child"
特点:
将父类属性复制到子类实例优点:解决引用属性共享问题缺陷:无法继承父类原型上的方法场景:
需要实例属性独立性的场景(如每个对象需要独立状态)不支持子类复用父类原型方法(若无需复用则合适)三、组合继承(经典继承)
实现方式:
function Parent(name) { this.name = name;}Parent.prototype.say = function() { return this.name };function Child(name) { Parent.call(this, name); // 第1次调用父类构造函数}Child.prototype = new Parent(); // 第2次调用父类构造函数(问题根源)Child.prototype.constructor = Child;const child = new Child('Child');child.say(); // 输出 "Child"
特点:
结合原型链继承(方法继承)和构造函数继承(属性继承)缺陷:父类构造函数被调用两次,子类原型中存在冗余属性场景:
传统项目的常规继承需求(ES6 出现前的常见方案)需要同时满足方法复用和实例属性独立的场景四、原型式继承
实现方式:
const parent = { name: 'Parent', friends: ['Alice'] };const child = Object.create(parent); // 核心APIchild.name = 'Child';child.friends.push('Bob'); // friends被所有基于parent创建的对象共享
特点:
类似于对象浅拷贝问题:引用类型属性共享(与原型链相同)场景:
简单对象继承需求(无构造函数存在的场景)原型链的极简替代方案(如旧环境无Object.create
时的polyfill
)五、寄生式继承
实现方式:
function createChild(parent) { const obj = Object.create(parent); obj.sayHi = () => 'Hi'; // 添加额外方法 return obj;}const child = createChild({ name: 'Parent' });
特点:
工厂模式增强对象缺陷:方法无法复用,类似构造函数问题场景:
需要给对象快速扩展额外方法的场景不适合大型继承结构(复用性差)六、寄生组合式继承(最优解)
实现方式:
function inheritPrototype(Child, Parent) { const prototype = Object.create(Parent.prototype); // 创建父类原型的副本 prototype.constructor = Child; // 修复构造函数指向 Child.prototype = prototype; // 赋值给子类原型}function Parent(name) { this.name = name; }Parent.prototype.say = function() { return this.name; };function Child(name) { Parent.call(this, name); // 属性继承}inheritPrototype(Child, Parent); // 方法继承
特点:
只调用一次父类构造函数,避免组合继承的冗余问题保留完整的原型链结构场景:
现代项目推荐的标准继承方式适用于所有复杂继承需求(效率最高)七、ES6class继承
实现方式:
class Parent { constructor(name) { this.name = name } say() { return this.name }}class Child extends Parent { // extends 关键字 constructor(name) { super(name); // super调用父类构造函数 }}const child = new Child('Child');child.say(); // 输出 "Child"
特点:
语法糖,本质基于原型和寄生组合式继承支持static
、super
等特性场景:
现代项目首选方式需要清晰类结构、继承关系明确的场景总结与场景对比
实际开发建议:
优先使用 ES6class
继承(清晰、易维护,Babel 转译后底层使用寄生组合式继承)旧项目维护时根据现有模式选择组合或寄生组合继承4️⃣原型式/寄生式继承主要用于对象克隆而非类继承场景