JavaScript实现继承的7种方式总结

当需要实现JavaScript继承时,可以使用以下七种方式:

一、原型链继承

  1. 将父类的实例作为子类的原型
  2. 优点:父类的属性和方法能够被继承
  3. 缺点:
    • 无法传递参数
    • 所有子类实例共享父类引用类型属性,容易影响其他子类实例

示例代码:

// 父类
function Parent (name) {
  this.name = name;
}

// 父类的方法
Parent.prototype.sayName = function() {
  console.log('My name is ' + this.name);
};

// 子类
function Child() {}

// 子类的原型指向父类的实例,实现继承
Child.prototype = new Parent('Jack');

// 子类的实例
var child = new Child();
child.sayName(); // 输出"My name is Jack"

二、借用构造函数继承(经典继承)

  1. 在子类构造函数中调用父类构造函数,使用apply或call改变this的指向
  2. 优点:
    • 可继承父类的属性和方法
    • 父类的引用类型属性不会在子类间共享
  3. 缺点:子类不能访问到父类原型上的方法

示例代码:

// 父类
function Parent(name){
  this.name = name;
  this.colors = ['red', 'green', 'blue'];
}

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

// 子类实例
var child1 = new Child('A', 18);
var child2 = new Child('B', 20);

// 修改child1的引用类型属性,不影响child2
child1.colors.push('yellow');
console.log(child1.colors); // 输出 ["red", "green", "blue", "yellow"]
console.log(child2.colors); // 输出 ["red", "green", "blue"]

三、组合继承

  1. 结合原型链继承和构造函数继承的优点
  2. 父类构造函数继承属性,子类的原型继承方法
  3. 缺点:构造函数执行两次,父类指定的属性和方法会被子类实例化两次

示例代码:

// 父类
function Parent(name){
  this.name = name;
  this.colors = ['red', 'green', 'blue'];
}

// 父类的方法
Parent.prototype.sayName = function() {
  console.log('My name is ' + this.name);
};

// 子类,借用构造函数继承父类的属性,使用原型链继承父类的方法
function Child(name, age){
  Parent.call(this, name);
  this.age = age;
}

Child.prototype = new Parent();

// 子类的方法
Child.prototype.sayAge = function() {
  console.log('I am ' + this.age + ' years old.');
};

// 子类的实例
var child1 = new Child('A', 18);
var child2 = new Child('B', 20);

// 修改child1的引用类型属性,不影响child2
child1.colors.push("yellow");
console.log(child1.colors); // 输出 ["red", "green", "blue", "yellow"]
console.log(child2.colors); // 输出 ["red", "green", "blue"]

child1.sayName(); // 输出 "My name is A"
child1.sayAge();  // 输出 "I am 18 years old."

四、原型式继承

  1. 利用原型可以指向一个对象的特点,复制原对象,返回一个新的对象
  2. 缺点:引用类型会被子类共享

示例代码:

// 原对象
var person = {
  name: "Tom",
  colors: ["red", "blue", "green"]
};

// 继承方法
function object(o){
  function F(){}
  F.prototype = o;
  return new F();
}

// 子类,通过复制原对象实现继承
var child1 = object(person);
var child2 = object(person);

// 修改child1的引用类型属性,影响child2
child1.colors.push("yellow");
console.log(child1.colors); // 输出 ["red", "blue", "green", "yellow"]
console.log(child2.colors); // 输出 ["red", "blue", "green", "yellow"]

五、寄生式继承

  1. 在原型式继承的基础上,增强对象,返回一个新的对象
  2. 缺点:引用类型会被子类共享

示例代码:

// 原对象
var person = {
  name: "Tom",
  colors: ["red", "blue", "green"]
};

// 继承方法
function object(o){
  function F(){}
  F.prototype = o;
  return new F();
}

// 增强对象方法
function createAnother(o){
  var clone = object(o);
  clone.sayName = function(){
    console.log("My name is " + this.name);
  }
  return clone;
}

// 子类,通过增强对象的方法实现继承
var child1 = createAnother(person);
var child2 = createAnother(person);

// 修改child1的引用类型属性,影响child2
child1.colors.push("yellow");
console.log(child1.colors); // 输出 ["red", "blue", "green", "yellow"]
console.log(child2.colors); // 输出 ["red", "blue", "green", "yellow"]

child1.sayName(); // 输出 "My name is Tom"

六、寄生组合式继承

  1. 在组合继承的基础上,将父类原型实例化的过程插入到创建子类的构造函数中
  2. 缺点:无

示例代码:

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

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

// 继承方法
function object(o){
  function F(){}
  F.prototype = o;
  return new F();
}

function inheritPrototype(subType, superType){
  var prototype = object(superType.prototype);      // 创建父类原型的一个副本
  prototype.constructor = subType;                   //这个副本的构造器指向子类,这样就可以继承父类原型中的方法了。
  subType.prototype = prototype;                     // 修正子类的原型对象
}

// 子类,通过组合式继承实现继承
function Child(name, age){
  Parent.call(this, name);
  this.age = age;
}

inheritPrototype(Child, Parent);

// 子类的方法
Child.prototype.sayAge = function(){
  console.log("I am " + this.age + " years old.");
}

// 子类的实例
var child1 = new Child("Tom", 18);
var child2 = new Child("Jerry", 20);

// 修改child1的引用类型属性,不影响child2
child1.colors.push("yellow");
console.log(child1.colors); // 输出 ["red", "blue", "green", "yellow"]
console.log(child2.colors); // 输出 ["red", "blue", "green"]

child1.sayName(); // 输出 "My name is Tom"
child1.sayAge();  // 输出 "I am 18 years old."

七、ES6 class 继承

  1. 使用关键字class和关键字extends实现继承
  2. 缺点:需先精通面向对象编程,但是它简化了构造函数继承和原型继承的写法,且具有清晰、美观的语法

示例代码:

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

  // 父类的方法
  sayName(){
    console.log("My name is " + this.name);
  }
}

// 子类,通过ES6 class实现继承
class Child extends Parent{
  constructor(name, age){
    super(name);
    this.age = age;
  }

  // 子类的方法
  sayAge(){
    console.log("I am " + this.age + " years old.");
  }
}

// 子类的实例
var child1 = new Child("Tom", 18);
var child2 = new Child("Jerry", 20);

// 修改child1的引用类型属性,不影响child2
child1.colors.push("yellow");
console.log(child1.colors); // 输出 ["red", "blue", "green", "yellow"]
console.log(child2.colors); // 输出 ["red", "blue", "green"]

child1.sayName(); // 输出 "My name is Tom"
child1.sayAge();  // 输出 "I am 18 years old."

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

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

相关文章

  • [转载]什么情况下应该设置cudnn.benchmark=true?

    [转载]什么情况下应该设置cudnn.benchmark=true? 在深度学习中,使用GPU进行加速训练已经变得越来越普遍。但在使用GPU训练时,我们常常会遇到优化的问题,其中之一就是cudnn库的使用,而cudnn.benchmark的设置就成了解决该问题的一种重要方法。那么什么情况下应该设置cudnn.benchmark=true呢?让我们来探究一下。…

    其他 2023年3月28日
    00
  • Python+Requests+PyTest+Excel+Allure 接口自动化测试实战

    Python+Requests+PyTest+Excel+Allure 接口自动化测试实战 本攻略将详细介绍如何使用Python的Requests库、PyTest测试框架、Excel作为测试数据源以及Allure生成漂亮的测试报告进行接口自动化测试。 准备工作 安装Python:确保您的系统已经安装了Python,并配置好了环境变量。 安装依赖库:使用pip…

    other 2023年10月17日
    00
  • WPF控件模板与其触发器

    下面是关于WPF控件模板与其触发器的详细讲解攻略: 什么是WPF控件模板 WPF控件模板是一种可用于自定义控件外观和行为的技术,它通过定义控件的视觉树和控制流以达到这一目的。控件模板通常使用XAML定义。 WPF控件模板通常包括以下几个部分: 控件模板根元素 控件模板的触发器 Trigger 集合 控件模板中的控件元素以及控件元素的附加属性和事件处理程序 W…

    other 2023年6月26日
    00
  • windows磁盘API实践

    Windows磁盘API实践 在Windows系统上,文件/目录的操作离不开磁盘的读写操作。而在程序中进行磁盘读写操作的API有很多,各自有自己的特点和适用场景。这篇文章将介绍几种Windows磁盘API的使用方法,包括CreateFile、ReadFile、WriteFile等。 CreateFile CreateFile是用于创建或打开文件、目录、磁盘等…

    其他 2023年3月28日
    00
  • 少儿编程Scratch第一讲:Scratch完美的初体验

    少儿编程Scratch第一讲:Scratch完美的初体验 Scratch 是由麻省理工学院开发的一款免费的教育编程语言,专为 8 岁及以上的儿童设计。在 Scratch 中,孩子们可以通过堆积积木块的方式,简单易懂地编写出自己的程序。它不仅仅是个编程语言,更是一个儿童学习编程的完美平台。 通过 Scratch 的学习,孩子们可以提高逻辑思维能力、创造力和解决…

    其他 2023年3月28日
    00
  • LZZ净网小助手使用方法(强力拦截广告弹窗)

    LZZ净网小助手使用方法(强力拦截广告弹窗) 简介 LZZ净网小助手是一款用于拦截广告弹窗的浏览器扩展,可以提供更好的浏览体验。以下是详细的使用方法攻略。 步骤1:安装LZZ净网小助手 打开您的浏览器,访问扩展程序商店(如Chrome Web Store、Firefox Add-ons等)。 在搜索栏中输入“LZZ净网小助手”并搜索。 找到合适的扩展,并点击…

    other 2023年6月28日
    00
  • Fragment配合RadioGroup实现点击切换布局

    Fragment配合RadioGroup实现点击切换布局 在Android开发中,我们经常会需要在同一个Activity中切换多个不同的布局,这种情况下可以使用Fragment来实现。Fragment是Android自3.0版本以后推出的一种组件,它可以作为Activity中的一个子模块,能够独立地管理自己的界面和逻辑,也可以与其他Fragment组合在一起…

    其他 2023年3月28日
    00
  • Opencv+Python实现缺陷检测

    Opencv是一个开源的计算机视觉库,可以用于图像处理、计算机视觉、机器学习等领域。Python是一种高级编程语言,具有简单易学、易读易写等特点。结合Opencv和Python可以实现图像处理、计算机视觉等应用。本文将介绍如何使用Opencv和Python实现缺陷检测。 环境搭建 在使用Opencv和Python实现缺陷检测之前,需要先搭建好相应的开发环境。…

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