JavaScript继承模式粗探

JavaScript继承模式粗探

在 JavaScript 中实现继承的方式有很多,本文将介绍五种不同的继承模式,并通过示例代码进行说明和比较。

1. 原型链继承

原型链继承是最常见的一种继承方式,其基本思想是通过将子类的原型设为父类的实例实现继承。

function Parent() {
  this.name = 'parent';
  this.say = function() {
    console.log('Hello, I am ' + this.name);
  }
}

Parent.prototype.show = function() {
  console.log('show in parent');
}

function Child() {}

Child.prototype = new Parent(); // 子类的原型设为父类的实例

const child = new Child();
console.log(child.name); // parent
console.log(child.show()); // "show in parent"
console.log(child.say()); // "Hello, I am parent"

但是原型链继承有一个致命的缺陷,即父类的引用属性会被所有子类实例共享,容易导致修改一个子类实例的引用属性时,其他实例的引用属性也会跟着改变。

2. 借用构造函数继承

借用构造函数继承是通过调用父类的构造函数来实现继承。

function Parent(name) {
  this.name = name;
  this.say = function() {
    console.log('Hello, I am ' + this.name);
  }
}

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

const child1 = new Child('child1');
const child2 = new Child('child2');
console.log(child1.say()); // "Hello, I am child1"
console.log(child2.say()); // "Hello, I am child2"

但是借用构造函数继承的缺点是无法继承父类原型上的方法和属性。

3. 组合继承

组合继承是将原型链继承和借用构造函数继承结合起来,既能继承父类构造函数中的属性,又能继承父类原型上的方法。

function Parent(name) {
  this.name = name;
  this.say = function() {
    console.log('Hello, I am ' + this.name);
  }
}

Parent.prototype.show = function() {
  console.log('show in parent');
}

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

Child.prototype = new Parent(); // 将子类的原型设为父类的实例
Child.prototype.constructor = Child; // 修正constructor

const child = new Child('child');
console.log(child.name); // child
console.log(child.show()); // "show in parent"
console.log(child.say()); // "Hello, I am child"

可以看到,组合继承综合了原型链继承和借用构造函数继承的优点,但是存在一个缺点就是在使用子类生成对象时,调用了两次父类构造函数,第一次是在将子类原型指向父类实例时,第二次是在子类构造函数中。

4. 原型式继承

原型式继承是基于某个对象创建一个副本作为新对象的原型,然后扩展新对象,从而实现继承。

const parent = {
  name: 'parent',
  say: function() {
    console.log('Hello, I am ' + this.name);
  }
}

const child = Object.create(parent); // 基于parent创建child的原型
child.name = 'child';

console.log(child.say()); // "Hello, I am child"

但是原型式继承也存在跟原型链继承相同的问题,即引用类型的属性会被所有实例共享。

5. 寄生式继承

寄生式继承是在原型式继承的基础上,将扩展对象的过程封装在函数中,返回新对象。

const parent = {
  name: 'parent',
  say: function() {
    console.log('Hello, I am ' + this.name);
  }
}

function createChild(obj, name) {
  const child = Object.create(obj);
  child.name = name;
  return child;
}

const child = createChild(parent, 'child');
console.log(child.say()); // "Hello, I am child"

总结

前面介绍了五种 JavaScript 继承模式,每种继承方式都有其优缺点,可以根据具体场景选择不同的继承方式,实现对象的多态。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript继承模式粗探 - Python技术站

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

相关文章

  • 详解C++值多态中的传统多态与类型擦除

    详解C++值多态中的传统多态与类型擦除 本文主要讲解C++中的多态,其中包括传统多态和类型擦除两种方式。 传统多态 什么是传统多态 传统多态是指在C++中,基类类型的指针或引用可以指向其派生类的对象,从而实现多态的特性,可以通过虚函数表来实现运行时的动态绑定。 如何实现传统多态 我们通过一个简单的示例来说明传统多态的实现过程。如下所示,我们定义了一个动物类和…

    other 2023年6月26日
    00
  • 在PHP中利用XML技术构造远程服务(下)

    下面是详细的攻略,分为两部分。 第一部分:准备工作 1. 安装xmlrpc扩展 要使用XML技术构建远程服务,需要在PHP中安装XMLRPC扩展。可以执行以下命令来安装扩展: sudo apt-get install php-xmlrpc 2. 编写服务端代码 PHP中的XML-RPC扩展提供了一个xmlrpc_server类,可以用于创建XML-RPC服务…

    other 2023年6月27日
    00
  • this.$message.success(‘提示信息’)少写了一个c导致报错

    以下是“this.$message.success(‘提示信息’)少写了一个c导致报错”的完整攻略,过程中包含两个示例说明的标准Markdown格式文本: this.$message.success(‘提示信息’)少写了一个c导致报错的完整攻略 在Vue.js中,我们经常使用this.$message.success(‘信息’)来显示成功提示信息。但是,有时…

    other 2023年5月10日
    00
  • Java 类加载过程与类加载器详细介绍

    让我为您讲解一下 “Java 类加载过程与类加载器详细介绍” 的完整攻略。 什么是类加载? Java 语言是一种面向对象程序设计语言,其中最基本的组成单位是类。在 Java 语言中,类是由编译器编译 Java 代码后生成的字节码文件,这些字节码文件最终是由 Java 虚拟机来执行的。而在 Java 虚拟机的执行过程中,类加载器则负责将类文件加载到 JVM 中…

    other 2023年6月25日
    00
  • redhat linux 安装 gcc编译器

    Red Hat Linux安装GCC编译器攻略 步骤1:检查GCC是否已安装 在终端中运行以下命令检查GCC是否已安装: gcc –version 如果GCC已安装,将显示GCC的版本信息。如果未安装,继续以下步骤。 步骤2:更新软件包列表 在终端中运行以下命令更新软件包列表: sudo yum update 这将更新系统的软件包列表,确保安装最新的软件包…

    other 2023年10月13日
    00
  • C++类中的特殊成员函数示例详解

    下面我来详细讲解“C++类中的特殊成员函数示例详解”的攻略。 一、什么是C++类中的特殊成员函数? 在C++中,类和结构体都有一些特殊的成员函数,也称为特殊成员函数。这些函数在特定情况下会自动创建或者被调用。C++中的特殊成员函数有以下几种: 默认构造函数 拷贝构造函数 拷贝赋值函数 移动构造函数 移动赋值函数 析构函数 二、示例说明 1. 默认构造函数 默…

    other 2023年6月26日
    00
  • JavaScript 变量作用域分析

    JavaScript 变量作用域分析攻略 在 JavaScript 中,变量作用域是指变量在代码中可访问的范围。了解变量作用域对于编写可维护和可扩展的代码非常重要。本攻略将详细讲解 JavaScript 变量作用域的概念和使用。 全局作用域 全局作用域是指在代码的任何地方都可以访问的变量。在 JavaScript 中,如果变量在任何函数之外声明,它就是一个全…

    other 2023年8月19日
    00
  • Java递归算法遍历部门代码示例

    关于Java递归算法遍历部门代码示例的攻略如下: 什么是递归算法 递归算法是指在函数中调用自己的算法。在递归算法中,问题会被分解成一个或多个规模更小的子问题,然后再逐个解决这些子问题,最终得到原始问题的解。 递归算法在遍历部门代码中的应用 在遍历部门代码时,递归算法可以很好地应用于处理树形结构数据。例如,一个公司的部门可以被看做是一个树形结构,其中每个部门都…

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