一文详解如何用原型链的方式实现JS继承

下面就来详细讲解一下如何用原型链的方式实现JS继承。

1. 什么是原型链

在JavaScript中,万物皆对象,每个对象都有 __proto__ 属性,指向了它的原型对象。原型对象也是一个对象,也有 __proto__ 属性,指向了它的原型对象。这样的对象构成了一个链状结构,被称为原型链。

2. 如何用原型链实现JS继承

原理很简单,就是在子类的原型对象上添加父类的实例作为子类的原型对象。

下面是一个例子,首先定义一个父类 Animal:

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

Animal.prototype.say = function() {
  console.log(`我的名字是${this.name}`);
}

再定义一个子类 Dog,并将其原型对象指向 Animal 的实例:

function Dog(name, age) {
  Animal.call(this, name);
  this.age = age;
}

Dog.prototype = new Animal();

Dog.prototype.bark = function() {
  console.log(`我的名字是${this.name},我${this.age}岁了`);
}

Dog 构造函数中,调用 Animal 构造函数,使 Dog 实例具有 Animal 实例的属性。然后将 Dog 的原型对象指向 Animal 的实例,使 Dog 实例可以继承 Animal 实例的方法。

现在我们创建一个 Dog 的实例:

const dog = new Dog("旺财", 3);

然后调用 Dog 实例的 barksay 方法:

dog.bark();  // 我的名字是旺财,我3岁了
dog.say();   // 我的名字是旺财

这就是原型链实现 JS 继承的基本过程。

3. 原型链继承存在的问题

使用原型链继承虽然简单,但也存在一些问题:

  • 所有子类实例共享父类实例,无法使用父类传参
  • 对父类实例的属性修改会反映到所有子类实例上
  • 无法实现多继承

下面是一个示例,说明原型链继承存在上述问题:

function Person(name) {
  this.name = name;
  this.hobbies = [];
}

Person.prototype.say = function() {
  console.log(`我的名字是${this.name}`);
}

function Student(name, grade) {
  this.grade = grade;
}

Student.prototype = new Person();

const stu1 = new Student("小明", 3);
const stu2 = new Student("小红", 2);

stu1.hobbies.push("读书");
stu2.hobbies.push("画画");

console.log(stu1.hobbies); // 输出 [ '读书', '画画' ]
console.log(stu2.hobbies); // 输出 [ '读书', '画画' ]

由于 Person 类的原型实例被多个 Student 类实例共享,所以它们的 hobbies 属性会相互影响。

4. 如何解决原型链继承的问题

解决原型链继承的问题,可以有以下几种方法:

4.1 借用构造函数

使用 call 或 apply 方法,在子类构造函数中调用父类构造函数,这样就可以在子类实例上创建一个独立的属性副本。

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

function Dog(name, age) {
  Animal.call(this, name);
  this.age = age;
}

const dog = new Dog("旺财", 3);
console.log(dog.name);  // 输出 旺财
console.log(dog.age);   // 输出 3

通过 call(this, ...) 将父类构造函数绑定到子类实例上,就可以在子类实例上创建一个独立的属性副本。

4.2 组合继承

组合继承就是将原型链继承和借用构造函数组合起来使用。首先使用原型链继承父类的原型对象,然后在子类构造函数中使用 call 或 apply 方法调用父类构造函数,以创建子类实例上的独立属性。

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

Animal.prototype.say = function() {
  console.log(`我的名字是${this.name}`);
}

function Dog(name, age) {
  Animal.call(this, name);
  this.age = age;
}

Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
  console.log(`我的名字是${this.name},我${this.age}岁了`);
}

const dog = new Dog("旺财", 3);
console.log(dog.name);  // 输出 旺财
console.log(dog.age);   // 输出 3
dog.say();              // 输出 我的名字是旺财
dog.bark();             // 输出 我的名字是旺财,我3岁了

Dog.prototype = new Animal()Animal.call(this, name) 这两行组合起来就实现了组合继承。首先使用原型链继承父类的原型对象,然后在子类构造函数中调用父类构造函数,以创建子类实例上的独立属性。

4.3 原型式继承

使用 Object.create(proto) 方法,创建一个空对象,并将其原型对象指向一个对象。这样这个空对象就可以继承这个对象的方法和属性。

const animal = {
  say() {
    console.log(`我的名字是${this.name}`);
  }
}

const dog = Object.create(animal);
dog.name = "旺财";
dog.say();     // 输出 我的名字是旺财

在这个例子中 dog 对象的原型对象是 animal 对象,所以它可以调用 animal 对象的方法。

4.4 寄生式继承

寄生式继承其实是对原型式继承的一种封装。实现方法与原型式继承类似,不同的是需要在构造函数中返回一个实现了特定方法的对象。

function createDog(animal, name, age) {
  const dog = Object.create(animal);
  dog.name = name;
  dog.age = age;
  dog.bark = function() {
    console.log(`我的名字是${this.name},我${this.age}岁了`);
  }
  return dog;
}

const animal = {
  say() {
    console.log(`我的名字是${this.name}`);
  }
}

const dog = createDog(animal, "旺财", 3);
dog.say();   // 输出 我的名字是旺财
dog.bark();  // 输出 我的名字是旺财,我3岁了

createDog 函数中,使用 Object.create 方法创建一个空对象,并继承了 animal 对象的方法和属性,然后在这个空对象中添加独有的属性和方法,最后返回这个对象,以实现一种新的继承方式。

5. 总结

以上就是使用原型链实现 JS 继承的攻略,总的来说原型链继承是 JS 中最基本的继承方式之一,而组合继承则是最常用的继承方式之一。在实际开发中可以根据需求选择合适的继承方式,也可以结合多种方式来实现。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:一文详解如何用原型链的方式实现JS继承 - Python技术站

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

相关文章

  • Win7旗舰版连接打印机报错0x00000002怎么办 错误代码0x00000002解决办法

    Win7旗舰版连接打印机报错0x00000002的解决办法 在连接打印机的时候,有部分用户可能会遇到Win7旗舰版连接打印机报错0x00000002的情况,即系统提示“无法连接到打印机,错误代码0x00000002”的错误信息,导致无法正常使用打印机。这种情况下,应该如何解决呢?下面我们提供一些解决方法。 方法一:删除打印机驱动 这种情况下,我们可以尝试删除…

    other 2023年6月27日
    00
  • IOS使用TestFlight测试的使用方法

    下面我将为你详细讲解 iOS 使用 TestFlight 测试的使用方法。 什么是 TestFlight TestFlight 是一个由苹果公司提供的用于 iOS 应用的 beta 测试平台。通过 TestFlight,开发者可以将应用测试版本发送给测试者,让他们在测试版中使用和体验应用,测试者还可以向开发者提供反馈和 bug 报告。TestFlight 有…

    other 2023年6月28日
    00
  • 后缀名是zip的文件用什么打开,如何打开zip文件?

    后缀名是zip的文件用什么打开? 后缀名为.zip的文件是一种常见的压缩文件格式,可以使用多种工具来打开。以下是几种常用的方法: 文件管理器:大多数操作系统都提供了内置的文件管理器,可以直接双击.zip文件来打开。例如,在Windows操作系统中,你可以使用资源管理器,而在Mac操作系统中,你可以使用Finder。 解压缩软件:如果你需要对.zip文件进行更…

    other 2023年8月5日
    00
  • spss19软件怎么安装?IBM SPSS Statistics 19安装破解图文详细教程(附代码)

    当您需要安装SPSS19软件时,可以按照以下步骤进行操作: 步骤一:安装准备 下载IBM SPSS Statistics 19软件安装包,并解压缩。 如果电脑上已经安装了旧版SPSS软件,请先卸载旧版SPSS软件。 步骤二:安装软件 打开解压缩后的文件夹,找到”setup.exe”程序,右击选择以管理员权限运行。 选择语言界面,点击“下一步”。 选择 “I …

    other 2023年6月26日
    00
  • Android学习之基础知识四-Activity活动8讲(活动的灵活运用)

    Android学习之基础知识四-Activity活动8讲(活动的灵活运用) 在Android开发中,Activity是非常重要的一个组件,它负责用户界面的呈现和事件响应。在之前的文章中,我们已经学习了Activity的基础知识,本篇文章将为大家介绍Activity的灵活运用技巧,帮助大家更好地开发应用程序。 1. 启动Activity Activity的启动…

    其他 2023年3月28日
    00
  • PHP获取客户端真实IP地址的5种情况分析和实现代码

    PHP获取客户端真实IP地址的5种情况分析和实现代码 在PHP中,获取客户端真实IP地址是一个常见的需求。然而,由于网络环境的复杂性,有时候获取真实IP地址并不是一件简单的事情。下面将详细讲解5种情况下获取客户端真实IP地址的方法,并提供相应的实现代码。 1. 获取$_SERVER中的REMOTE_ADDR $ip = $_SERVER[‘REMOTE_AD…

    other 2023年7月30日
    00
  • mysql创建表添加字段注释的实现方法

    MySQL创建表添加字段注释的实现方法可以分为以下几个步骤: 步骤一:创建表 首先,我们需要在MySQL数据库中创建一个需要添加注释的表。具体的操作可以使用以下语句: CREATE TABLE `example` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT ‘主键’, `name` varchar(255) …

    other 2023年6月25日
    00
  • js控制只允许输入数字

    以下是关于如何使用JavaScript控制只允许输入数字的详细攻略: 步骤一:获取输入框元素 首先,需要获取要控制的输入框元素。可以使用 document() 方法或 document.querySelector() 方法获取元素。例如,要获取 id 为“inputNumber”的框元素,可以使用以下代码: constNumber = document.ge…

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