JavaScript 中常见的几种继承方式详解

作者:函数茶馆时间:2026-10-25 13:19:15浏览:224

本文详细解析 JavaScript 中几种常见的继承模式,包括原型继承、盗用构造函数继承、组合继承、原型链继承、寄生式继承以及被称为最佳实践的寄生组合式继承。通过原理分析与代码示例,对比各方式的优缺点,重点阐述如何解决属性共享、内存占用及父类方法调用次数等问题。

原型继承

function Parent(name) {
  this.name = name
}
Parent.prototype.getName = function(){
  return 'parentPrototype' + ' ' + this.name;
}
function Son() {
}
Son.prototype = new Parent();
console.log(new Son())

内存图

原型继承

原型继承

分析

原型继承的核心机制在于将子类的 prototype 属性指向父类的一个实例。通过这种设置,子类实例能够访问父类的属性和方法。然而,这种方式存在一个显著缺陷:无法在子类实例化时初始化父类的属性。针对这一局限,盗用构造函数继承方式应运而生。

盗用构造函数继承

function Parent(name) {
  this.name = name
}
Parent.prototype.getName = function(){
  return 'parentPrototype' + ' ' + this.name;
}
function Son(name) {
  Parent.call(this, name)
}

console.log(new Son('jack'))

分析

原型继承

盗用构造函数继承的基本原理是将父类函数的代码 copy 到子类内部。在上述示例中,这相当于在子类中执行了一次父类的 this.name = name。其优势在于,当创建子类实例时,可以成功初始化父类的部分属性。

若仅采用上述方式,子类将无法获取定义在父类原型对象上的方法。为了解决这一缺失,组合继承模式被提出。

组合继承

function Parent(name) {
  this.name = name
}
Parent.prototype.getName = function(){
  return 'parentPrototype' + ' ' + this.name;
}
function Son(name) {
  Parent.call(this, name) // 第二次调用
}
Son.prototype = new Parent() // 第一次调用
console.log(new Son('jack'))

组合继承,亦被称为伪经典继承,它融合了原型继承与盗用构造函数继承的优点。这种模式既能够在实例化时初始化父类属性,又能让子类访问到父类原型对象上的方法。

原型继承

观察该实现方式可以发现,属性 name 会被多次创建。尽管在功能使用上并无差异,但这会导致额外开辟无用内存空间,并且会多调用一次函数,造成一定的性能损耗。

原型链继承

const parent = {
  name: 'jack',
  getName() {
    return this.name
  }
}
const son = Object.create(parent)
console.log(son)

这种继承方式适用于希望基于一个现有对象创建新对象的场景,且该新对象可以拥有自己独立的属性。

原型继承

它同样允许定义自有属性:

const parent = {
  name: 'jack',
  getName() {
    return this.name
  }
}
const son = Object.create(parent, {
  age: {
    value: 18,
    enumerable: true,
    writable: true,
    configurable: true
  }
})
console.log(son)

原型继承

寄生式继承

const parent = {
  name: 'jack',
  getName() {
    return this.name
  }
}
function createObj(origin){
  const res = Object(origin);
  res.age = 18;
  res.getAge = function() {
    return this.age
  };
  return res
}
const son = createObj(parent)
console.log(son)

原型继承

寄生式继承的思路类似于工厂模式。经过该模式创建的函数或对象,会附带一些预设的值或增强功能。

寄生组合式继承

function Parent(name) {
  this.name = name;
}
Parent.prototype.getName = function () {
  return this.name;
}
function Son(name) {
  Parent.call(this, name)
};
function inhertPrototype(Son, Parent) {
  const res = Object(Parent.prototype); // 创建目标对象的原型对象
  // 可以理解为复制父类对象prototype的属性,这样做可以少调用一次父类的实例化操作
  res.constructor = Son // 将构造函数指向son
  Son.prototype = res //将子类的prototype 指向父类创建的原型对象,这样子类既可以使用父类的方法,又不用实例化父类
}
inhertPrototype(Son, Parent)
console.log(new Son('jack'))

寄生组合式继承被公认为最佳的继承模式。它解决了组合继承中父类函数被调用两次的问题,同时避免了给子类的 prototype 添加父类无用属性的情况。

原型继承

对比组合继承的图示可见,prototype 上少了 name ,这是最佳的继承方式。

到此这篇关于JavaScript中常见的几种继承方式的文章就介绍到这了,更多相关js继承方式内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

作者最新文章