javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > JavaScript继承方式

JavaScript继承的实现方式详解

作者:Peter-Lu

JavaScript 是一门基于原型的语言,它的继承机制与传统的基于类的面向对象编程有所不同,尽管 ES6 引入了 class 语法,但本质上仍然是基于原型链的继承,本文将详细介绍 JavaScript 继承的几种实现方式,需要的朋友可以参考下

引言

JavaScript 是一门基于原型的语言,它的继承机制与传统的基于类的面向对象编程(如 Java、C++)有所不同。尽管 ES6 引入了 class 语法,但本质上仍然是基于原型链的继承。本文将详细介绍 JavaScript 继承的几种实现方式,包括原型链继承、构造函数继承、组合继承、寄生组合继承,以及 ES6 class 继承,并分析它们的优缺点和适用场景。

一、JavaScript 继承的基本概念

在 JavaScript 中,每个对象都有一个原型(prototype),新创建的对象可以从原型对象继承属性和方法。继承的核心思想是:子类对象可以访问父类的属性和方法,从而实现代码复用。

JavaScript 主要提供了以下几种继承方式:

  1. 原型链继承
  2. 构造函数继承
  3. 组合继承(构造函数 + 原型链)
  4. 寄生组合继承(最优方案)
  5. ES6 class 继承

接下来,我们将逐一介绍这些继承方式的实现原理、代码示例以及优缺点。

二、原型链继承

1. 实现方式

原型链继承的核心思想是让子类的 prototype 指向父类的实例,这样子类就能访问父类的方法和属性。

function Parent() {
  this.name = "Parent";
  this.colors = ["red", "blue", "green"];
}

Parent.prototype.getName = function() {
  return this.name;
};

function Child() {}

Child.prototype = new Parent(); // 关键点:让子类的 prototype 指向父类实例

const child1 = new Child();
console.log(child1.getName()); // Parent
console.log(child1.colors); // ["red", "blue", "green"]

child1.colors.push("yellow");

const child2 = new Child();
console.log(child2.colors); // ["red", "blue", "green", "yellow"] (被修改了)

2. 存在的问题

三、构造函数继承

1. 实现方式

通过在子类的构造函数中调用父类构造函数,并使用 call() 或 apply() 绑定 this,从而避免原型链继承的问题。

function Parent(name) {
  this.name = name;
  this.colors = ["red", "blue", "green"];
}

function Child(name) {
  Parent.call(this, name); // 关键点:在子类构造函数中调用父类构造函数
}

const child1 = new Child("Child1");
const child2 = new Child("Child2");

child1.colors.push("yellow");

console.log(child1.colors); // ["red", "blue", "green", "yellow"]
console.log(child2.colors); // ["red", "blue", "green"] (不会被修改)

2. 解决的问题

3. 存在的问题

四、组合继承(构造函数 + 原型链)

1. 实现方式

组合继承结合了构造函数继承原型链继承的优点。

function Parent(name) {
  this.name = name;
  this.colors = ["red", "blue", "green"];
}

Parent.prototype.getName = function() {
  return this.name;
};

function Child(name, age) {
  Parent.call(this, name); // 调用父类构造函数,继承实例属性
  this.age = age;
}

Child.prototype = new Parent(); // 继承父类方法
Child.prototype.constructor = Child; // 修正 constructor 指向

const child1 = new Child("Child1", 18);
console.log(child1.getName()); // Child1
console.log(child1.colors); // ["red", "blue", "green"]

2. 解决的问题

3. 存在的问题

四、组合继承(构造函数 + 原型链)

1. 实现方式

组合继承结合了构造函数继承原型链继承的优点。

function Parent(name) {
  this.name = name;
  this.colors = ["red", "blue", "green"];
}

Parent.prototype.getName = function() {
  return this.name;
};

function Child(name, age) {
  Parent.call(this, name); // 调用父类构造函数,继承实例属性
  this.age = age;
}

Child.prototype = new Parent(); // 继承父类方法
Child.prototype.constructor = Child; // 修正 constructor 指向

const child1 = new Child("Child1", 18);
console.log(child1.getName()); // Child1
console.log(child1.colors); // ["red", "blue", "green"]

2. 解决的问题

3. 存在的问题

五、寄生组合继承(推荐方案)

1. 实现方式

寄生组合继承优化了组合继承中的 new Parent(),避免了父类构造函数的重复调用。

function Parent(name) {
  this.name = name;
  this.colors = ["red", "blue", "green"];
}

Parent.prototype.getName = function() {
  return this.name;
};

function Child(name, age) {
  Parent.call(this, name); // 继承属性
  this.age = age;
}

Child.prototype = Object.create(Parent.prototype); // 继承方法,但不会执行 Parent 构造函数
Child.prototype.constructor = Child; // 修正 constructor 指向

const child1 = new Child("Child1", 18);
console.log(child1.getName()); // Child1
console.log(child1.colors); // ["red", "blue", "green"]

2. 优点

六、ES6 class 继承(最现代化的方式)

1. 实现方式

ES6 引入 class 语法,使继承更加直观:

class Parent {
  constructor(name) {
    this.name = name;
    this.colors = ["red", "blue", "green"];
  }

  getName() {
    return this.name;
  }
}

class Child extends Parent {
  constructor(name, age) {
    super(name); // 继承父类属性
    this.age = age;
  }
}

const child1 = new Child("Child1", 18);
console.log(child1.getName()); // Child1
console.log(child1.colors); // ["red", "blue", "green"]

2. 优点

七、总结

继承方式主要特点优点缺点
原型链继承让子类 prototype 指向父类实例方法共享共享引用属性
构造函数继承使用 call 调用父类解决共享问题,可传参方法无法复用
组合继承构造函数 + 原型链解决共享问题调用两次父类构造函数
寄生组合继承最优 ES5 方案解决所有问题代码略复杂
ES6 class 继承最现代化方案语法简洁,推荐使用仅限 ES6+

在现代 JavaScript 开发中,建议 优先使用 ES6 class 继承,但在需要兼容旧浏览器时,可以使用 寄生组合继承

以上就是JavaScript继承的实现方式详解的详细内容,更多关于JavaScript继承方式的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文