JavaScript实现继承的6种常用方式总结

JavaScript实现继承的6种常用方式总结

本文主要介绍JavaScript实现继承的6种常用方式,包括原型链继承、构造函数继承、组合继承、寄生组合继承、ES6 class继承、Mixin继承。

1. 原型链继承

原型链继承是将子类的原型设置为父类的实例,通过原型链来实现继承。其实现步骤如下:

function Parent() {
  this.name = 'parent';
}

Parent.prototype.sayHello = function() {
  console.log('Hello from ' + this.name);
}

function Child() {}

Child.prototype = new Parent();

var child = new Child();
child.sayHello();

这种方式的缺陷是:所有子类实例共用一个父类实例,当修改某个子类实例中的属性时,其他子类实例的属性也会被修改。

2. 构造函数继承

构造函数继承是将父类的构造函数在子类中执行一遍,从而实现继承。其实现步骤如下:

function Parent(name) {
  this.name = name;
}

Parent.prototype.sayHello = function() {
  console.log('Hello from ' + this.name);
}

function Child(name) {
  Parent.call(this, name);
}

var child = new Child('child');
child.sayHello();

这种方式的缺陷是:父类原型中的方法对于子类而言是不可见的。

3. 组合继承

组合继承是将原型链继承和构造函数继承结合起来,实现同时继承父类构造函数属性和原型上的方法。其实现步骤如下:

function Parent(name) {
  this.name = name;
}

Parent.prototype.sayHello = function() {
  console.log('Hello from ' + this.name);
}

function Child(name) {
  Parent.call(this, name);
}

Child.prototype = new Parent();

var child = new Child('child');
child.sayHello();

这种方式的缺陷是:在调用两次父类构造函数,存在性能问题。

4. 寄生组合继承

寄生组合继承是在组合继承的基础上,通过优化避免了调用两次父类构造函数,其实现步骤如下:

function Parent(name) {
  this.name = name;
}

Parent.prototype.sayHello = function() {
  console.log('Hello from ' + this.name);
}

function Child(name) {
  Parent.call(this, name);
}

Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;

var child = new Child('child');
child.sayHello();

这种方式是目前使用最多的继承方式,常用于大型项目中。

5. ES6 class继承

ES6 class继承是通过class和extends关键字实现继承,其实现步骤如下:

class Parent {
  constructor(name) {
    this.name = name;
  }

  sayHello() {
    console.log('Hello from ' + this.name);
  }
}

class Child extends Parent {
  constructor(name) {
    super(name);
  }
}

var child = new Child('child');
child.sayHello();

逐渐取代了以前传统的继承方式,被广泛使用。

6. Mixin继承

Mixin继承是通过将多个对象混合在一起,实现继承。其实现步骤如下:

function mix(...mixins) {
  class Mixin {
    constructor() {
      for (let mixin of mixins) {
        copyProperties(this, new mixin());
      }
    }
  }

  for (let mixin of mixins) {
    copyProperties(Mixin, mixin);
    copyProperties(Mixin.prototype, mixin.prototype);
  }

  return Mixin;
}

function copyProperties(target, source) {
  for (let key of Reflect.ownKeys(source)) {
    if (key !== "constructor"
      && key !== "prototype"
      && key !== "name") {
      let des = Object.getOwnPropertyDescriptor(source, key);
      Object.defineProperty(target, key, des);
    } 
  }
}

class Parent {
  constructor(name) {
    this.name = name;
  }

  sayHello() {
    console.log('Hello from ' + this.name);
  }
}

class Child extends mix(Parent) {
  constructor(name) {
    super(name);
  }
}

var child = new Child('child');
child.sayHello();

这种方式适用于需要组合多个对象的项目中。

示例说明:

// 寄生组合继承示例
function Shape(x, y) {
  this.x = x;
  this.y = y;
}

Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.log('Shape moved.');
}

function Circle(x, y, r) {
  Shape.call(this, x, y);
  this.r = r;
}

Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.constructor = Circle;

Circle.prototype.getArea = function() {
  return Math.PI * this.r * this.r;
}

var circle = new Circle(10, 10, 5);
console.log(circle.getArea());
circle.move(5, 5);

// ES6 class继承示例
class Shape {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  move(x, y) {
    this.x += x;
    this.y += y;
    console.log('Shape moved.');
  }
}

class Circle extends Shape {
  constructor(x, y, r) {
    super(x, y);
    this.r = r;
  }

  getArea() {
    return Math.PI * this.r * this.r;
  }
}

var circle = new Circle(10, 10, 5);
console.log(circle.getArea());
circle.move(5, 5);

以上代码分别演示了寄生组合继承和ES6 class继承的实现和使用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript实现继承的6种常用方式总结 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • Linux下java环境配置图文方法

    下面是详细讲解“Linux下java环境配置图文方法”的完整攻略。 Linux下java环境配置图文方法 1. 检查是否已安装Java 在终端中输入以下命令,检查是否已安装Java: java -version 如果已安装,会显示Java版本信息,否则会提示“Command not found”。 2. 安装Java 如果未安装Java,可以按照以下步骤安装…

    other 2023年6月27日
    00
  • healthd电池battery

    以下是“healthd电池battery”的完整攻略: healthd电池battery healthd是一个Linux系统中的守护进程,它可以监控系统健康状况,包括电池状态。本攻略绍如何使用healthd来监控电池状态。 步骤1:安装healthd 在开始使用healthd之前,您需要在Linux系统中装healthd。您可以使用以下命令在Ubuntu系统…

    other 2023年5月7日
    00
  • CSS3 选择器 基本选择器介绍

    CSS3 选择器 基本选择器介绍 1. id选择器 id选择器通过元素的id属性来选择元素。它以”#id”的格式表示。 示例: #myElement { color: red; } 上述例子中,选择器”#myElement”会选择具有id属性值为”myElement”的元素,并将其文本颜色设置为红色。 2. 类选择器 类选择器通过元素的class属性来选择元…

    other 2023年6月28日
    00
  • github概述

    GitHub 概述 GitHub 是一个基于互联网的代码托管平台,可以帮助开发者存储、管理和分享代码。本文将详细介绍 GitHub 的概述,包括基本概念、功能特点、使用方法和示例说明。 基本概念 GitHub 是一个基于互联网的代码托管平台,由 Chris Wanstrath、PJ Hyett 和 Preston-Werner 于 2008 年创建。GitH…

    other 2023年5月6日
    00
  • mysql数据类型decimal用法详解

    MySQL数据类型DECIMAL用法详解 在MySQL中,DECIMAL是一种数字数据类型,用于存储固定精度的十进制数。下面详细介绍MySQL数据类型DECIMAL的用法。 DECIMAL类型的定义 DECIMAL的精度定义如下: DECIMAL(M, D) 其中M表示总位数,D表示小数的位数,范围为0到M。例如,DECIMAL(5, 2)表示总共5位,其中…

    其他 2023年3月28日
    00
  • 详细讲解Java抽象类示例

    详细讲解Java抽象类示例 什么是Java抽象类 Java抽象类是一种不能被实例化的类,其目的是为了让其子类进行实现(即继承)其抽象方法。Java抽象类的关键字是abstract。 Java抽象类有以下特点: 抽象类不能被实例化。 抽象类可以包含非抽象方法。 抽象类必须包含至少一个抽象方法。 子类必须实现(override)其父类的所有抽象方法,否则子类也必…

    other 2023年6月26日
    00
  • react脚手架如何配置less和ant按需加载的方法步骤

    当我们使用React构建应用程序时,经常需要使用Less来实现样式和Ant Design来使用React组件。为了提高项目的性能,我们需要将Ant Design的组件进行按需加载,这样可以避免打包生成体积较大的文件。以下是配置步骤: 安装依赖 首先需要安装React、React-DOM、Ant Design、Less、Less-loader: npm ins…

    other 2023年6月26日
    00
  • java队列之queue用法实例分析

    Java队列之Queue用法实例分析 什么是队列? 队列是一种特殊的线性数据结构,按照先进先出(First In First Out,FIFO)的原则存储数据,在队列的一端添加数据,在另一端删除数据,有点像排队买东西,先来的先买,后来的后买。 在Java中,队列的实现方式是使用Queue接口,Queue是Java中表示队列的接口,它继承了Collection…

    other 2023年6月27日
    00
合作推广
合作推广
分享本页
返回顶部