JavaScript是如何实现继承的(六种方式)

yizhihongxing

下面是 JavaScript 实现继承的六种方式的详细攻略:

1. 原型链继承

原型链继承是 JavaScript 实现继承最常用的方式之一。通过将子类的原型指向父类的实例,从而实现对父类属性和方法的继承。具体代码实现如下:

// 父类
function Person(name) {
  this.name = name;
}
Person.prototype.sayName = function () {
  console.log("My name is " + this.name + ".");
};

// 子类
function Student(name, grade) {
  this.grade = grade;
}
Student.prototype = new Person();

// 实例化子类
let s1 = new Student("Tom", "3");
s1.sayName(); // 输出 "My name is Tom."

这里我们将子类的原型 Student.prototype 指向了父类的实例 new Person(),这样子类的实例 s1 就可以直接访问父类 Person 的属性和方法了。

一个注意点是,子类自身定义的属性或方法会覆盖继承来的父类属性或方法,例如:

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

  this.sayName = function () {
    console.log("I am Student, my name is " + this.name + ".");
  };
}

let s2 = new Student("Tony", "5");
s2.sayName(); // 输出 "I am Student, my name is Tony."

上面的 sayName 方法覆盖了父类 Person 的同名方法。

2. 借用构造函数

借用构造函数是在子类构造函数内部通过 callapply 调用父类构造函数的方式实现继承。但是借用构造函数只能继承父类的属性,不能继承方法。具体代码实现如下:

// 父类
function Person(name) {
  this.name = name;
  this.sayName = function () {
    console.log("My name is " + this.name + ".");
  };
}

// 子类
function Student(name, grade) {
  Person.call(this, name); // 借用父类的构造函数初始化属性
  this.grade = grade;
}

// 实例化子类
let s3 = new Student("Jack", "2");
s3.sayName(); // 报错,父类的方法没有被继承
console.log(s3.name); // 输出 "Jack"

我们在子类的构造函数中通过 Person.call(this, name) 调用了父类 Person 的构造函数,从而实现对父类实例属性 name 的继承。但是由于没有继承父类的方法,所以调用 s3.sayName() 会报错。

3. 组合继承

组合继承是原型链继承和借用构造函数组合起来的方式。它通过原型链继承父类的方法和通过借用构造函数继承父类的属性两种方式结合来实现继承。具体代码实现如下:

// 父类
function Person(name) {
  this.name = name;
}
Person.prototype.sayName = function () {
  console.log("My name is " + this.name + ".");
};

// 子类
function Student(name, grade) {
  Person.call(this, name);
  this.grade = grade;
}

Student.prototype = new Person(); // 原型链继承父类的方法
Student.prototype.constructor = Student; // 修复构造函数

// 实例化子类
let s4 = new Student("Mary", "1");
s4.sayName(); // 输出 "My name is Mary."
console.log(s4.name, s4.grade); // 输出 "Mary 1"

在这里我们既用到了原型链继承父类的方法,也通过借用构造函数继承了父类的属性,达到了全面继承的效果。

需要注意的是,由于子类的原型 Student.prototype 被重新赋值为了父类的实例 new Person(),所以需要额外修复一下子类的构造函数指向。

4. 原型式继承

原型式继承是通过指定一个基础对象来创建子类,实现对基础对象属性和方法的继承。具体代码实现如下:

// 基础对象
let baseObj = {
  name: "",
  sayName: function () {
    console.log("My name is " + this.name + ".");
  },
};

// 创建子类
let s5 = Object.create(baseObj);
s5.name = "Linda";

s5.sayName(); // 输出 "My name is Linda."
console.log(s5.name); // 输出 "Linda"

在这里我们用 Object.create 方法创建了一个新对象 s5,并指定了基础对象 baseObj 作为它的原型,从而实现了对基础对象的属性和方法的继承。

5. 寄生式继承

寄生式继承是在原型式继承的基础上增强了对象的功能。具体代码实现如下:

// 基础对象
let baseObj2 = {
  name: "",
  sayName: function () {
    console.log("My name is " + this.name + ".");
  },
};

// 增强对象的功能
let subObj = Object.create(baseObj2);
subObj.sayHi = function () {
  console.log("Hi, I am " + this.name + ".");
};

// 创建子类
let s6 = Object.create(subObj);
s6.name = "John";

s6.sayHi(); // 输出 "Hi, I am John."
console.log(s6.name); // 输出 "John"

在这里我们对原型式继承创建的对象 subObj 增加了一个 sayHi 方法,然后在它的基础上创建了新对象 s6。新对象依然继承了 baseObj2 的属性和方法,同时也有了自己的方法 sayHi

6. 寄生组合式继承

寄生组合式继承是在组合继承的基础上进行了优化,避免了父类构造函数被调用两次的问题。具体代码实现如下:

// 父类
function Person(name) {
  this.name = name;
}
Person.prototype.sayName = function () {
  console.log("My name is " + this.name + ".");
};

// 子类
function Student(name, grade) {
  Person.call(this, name); // 借用构造函数继承属性
  this.grade = grade;
}
Student.prototype = Object.create(Person.prototype); // 原型式继承方法
Student.prototype.constructor = Student; // 修复构造函数

// 实例化子类
let s7 = new Student("Lucy", "4");
s7.sayName(); // 输出 "My name is Lucy."
console.log(s7.name, s7.grade); // 输出 "Lucy 4"

在这里我们使用 Object.create 方法实现了对父类原型 Person.prototype 的继承,同时用 call 方法调用了父类构造函数,并且也修复了子类的构造函数。

以上就是 JavaScript 实现继承的六种方式的详细攻略和示例说明。希望能够对你有所帮助!

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript是如何实现继承的(六种方式) - Python技术站

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

相关文章

  • iPhone快速添加网址URL后缀技巧不需要一个一个的去输入

    iPhone快速添加网址URL后缀技巧攻略 在iPhone上,我们可以使用一些技巧来快速添加网址URL后缀,而不需要一个一个地输入。下面是一个完整的攻略,包含两个示例说明。 使用“.”快速添加.com后缀 打开Safari浏览器并进入网址输入栏。 输入网址的主体部分,例如 \”www.example\”。 在键盘上长按“.”键,会弹出一个快捷菜单。 在快捷菜…

    other 2023年8月5日
    00
  • spring+rabbitmq+stomp搭建websocket消息推送(非springbo…

    Spring + RabbitMQ + Stomp 搭建 WebSocket 消息推送(非 Spring Boot 版本) WebSocket 是一项在 Web 开发中非常重要的技术,它允许服务器和客户端之间实时、双向通信。在实际开发过程中,我们通常需要使用一些消息队列来实现后台消息推送系统,而 RabbitMQ 是一个非常优秀的消息队列实现。本文将介绍如何…

    其他 2023年3月28日
    00
  • spring boot 即时重新启动(热更替)使用说明

    以下是关于如何在Spring Boot项目中实现即时重新启动(热更替)的完整攻略。 1. 添加Spring Boot的devtools依赖 首先,在pom.xml文件中添加devtools依赖,如下所示: <dependencies> <!– 添加DevTools依赖 –> <dependency> <group…

    other 2023年6月27日
    00
  • rasrc4aes加密md5

    以下是关于RSA、RC4、AES加密和MD5哈希算法的完整攻略,包括算法原理、加密过程、示例说明等。 1. RSA加密算法 RSA加密算法是一种公钥加密法,它使用一对公钥和私钥来进行加密和解密操作。以下是RSA加密算法加密过程: 密钥:生成一对公钥和私钥。 加密:使用公钥对明文进行加密。 解密:使用私钥对密文进行解密。 以下是一个使用RSA加密算的示例说明:…

    other 2023年5月7日
    00
  • jquery点击事件失效原因和解决办法

    jQuery点击事件失效原因和解决办法 在使用jQuery编写网页时,我们经常会使用点击事件来响应用户的操作。但是,有时候我们会遇到事件失效的问题。本攻略将介绍点击事件失效的原因和解决办法。 原因1:元素不存在 当我们使用jQuery绑定点击事件时,如果元素不存在,那么点击事件就会失效。以下是一个示例代码: $(document).ready(functio…

    other 2023年5月7日
    00
  • keil5创建基于rtx的stm32工程(转载+自己的体会)

    Keil5创建基于RTX的STM32工程(转载+自己的体会) RTX是一款由Keil开发的嵌入式操作系统,提供了一套完整的多线程编程解决方案,适用于多个主流处理器平台,其中包括ST的STM32平台。在Keil5中,创建基于RTX的STM32工程也是非常简单的。本文将介绍如何使用Keil5来创建一个基于RTX的STM32工程,并分享一些自己的经验和体会。 步骤…

    其他 2023年3月29日
    00
  • lumion材质系统室内渲染6.3

    Lumion材质系统室内渲染6.3 Lumion是一款专业的实时渲染软件,已经被广泛应用于建筑、室内设计、景观设计等领域。Lumion 6.3版本中新增加了材质系统,极大地提高了室内场景的渲染效果和表现力。 材质系统的介绍 Lumion 6.3中新增加的材质系统,可以对模型的表面进行材质映射、标准化和纹理映射等操作,大大提高了模型表现的效果,让室内渲染效果更…

    其他 2023年3月28日
    00
  • base64之js压缩图片

    base64之js压缩图片 在Web开发中,图像文件传输占据了极大的带宽。为此,我们可以使用一些方法来减少图像传输的大小。其中,将图像压缩为base64编码字符串并将其添加到HTML或CSS文件中是一种常见的方法。在这篇文章中,我们将学习如何使用JavaScript对图像进行压缩,并将其转换为base64编码字符串以缩小文件的大小。 为什么要使用base64…

    其他 2023年3月28日
    00
合作推广
合作推广
分享本页
返回顶部