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日

相关文章

  • uniapp导入导出excel

    uniapp导入导出excel攻略 在uniapp中,可以使用js-xlsx库实现导入导出excel。以下是详细的攻略: 步骤 以下是导入导出excel的步骤: 安装-xlsx库。 在uniapp项目中,使用npm安装js-xlsx库。 bash npm install xlsx –save 导入excel文件。 在uniapp中,可以使用uni.choo…

    other 2023年5月7日
    00
  • 什么是操作系统?

    操作系统是指一组系统软件,它们管理计算机的硬件和软件资源,为用户和应用程序提供统一的接口和服务。操作系统的攻略可以分为以下几个方面: 学习操作系统的基础知识,包括操作系统的概念、功能和特点,以及常见的操作系统类型和体系结构。 掌握操作系统的设计和实现原理,包括进程管理、内存管理、文件系统、设备管理等子系统的设计和实现方法。 熟悉操作系统的开发环境和工具,包括…

    其他 2023年4月19日
    00
  • Python性能调优的十个小技巧总结

    Python性能调优的十个小技巧总结 在Python编程中,性能调优是一个重要的方面,可以提高程序的执行效率和响应速度。下面是十个小技巧,可以帮助你优化Python代码的性能。 1. 使用局部变量 在循环或函数中,尽量使用局部变量而不是全局变量。因为局部变量的访问速度更快,可以减少函数调用和内存访问的开销。 示例: def calculate_sum(num…

    other 2023年7月29日
    00
  • ios学习——uialertcontroller详解

    iOS学习——UIAlertController详解 在iOS开发中,弹窗是必不可少的一个组件。UIAlertController是iOS 8之后引入的一个更加强大和灵活的弹窗组件,取代了之前的UIAlertView和UIActionSheet。本文将详细介绍UIAlertController的用法和相关属性。 UIAlertController的类型 UI…

    其他 2023年3月29日
    00
  • C++递归删除一个目录实例

    要递归删除一个目录,可以使用以下步骤: 使用built-in函数或者第三方库来获取目录下的所有文件和子目录 遍历所有子目录,并递归调用删除子目录的函数 遍历所有文件,并通过系统调用或者库函数将其删除 最终删除根目录 下面是一个标准的C++代码示例,调用了Windows API函数来实现删除目录的操作: #include <iostream> #i…

    other 2023年6月27日
    00
  • 快速构建Windows 8风格应用1-开发工具安装及模拟器使用

    快速构建Windows 8风格应用1-开发工具安装及模拟器使用攻略 本文将详细介绍如何快速构建Windows 8风格应用,包括开发工具的安装和模拟器的使用。本文将提供两个示例说明。 开发工具安装 在构建Windows 8风格应用之前,需要安装Visual Studio 2012或更高版本的开发工具。以下是安装步骤: 下载Visual Studio 2012或…

    other 2023年5月5日
    00
  • vue-cli4.x创建企业级项目的方法步骤

    下面是详细讲解“vue-cli4.x创建企业级项目的方法步骤”的完整攻略。 步骤一:安装Node.js和Vue.js 首先,我们需要在本地电脑上安装Node.js。我们可以在官网上下载符合自己系统的安装包并安装完成。完成Node.js的安装后,我们需要使用npm命令安装Vue.js。安装Vue.js的方法如下: npm install vue 步骤二:安装V…

    other 2023年6月27日
    00
  • Win11 Build 2262x.1690 Beta 预览版今日发布(附KB5026447更新内容汇总)

    Win11 Build 2262x.1690 Beta 预览版攻略 介绍 Win11 Build 2262x.1690 Beta 是 Windows 11 操作系统的最新预览版。本攻略将详细介绍该版本的更新内容和一些示例说明。 更新内容 KB5026447 更新内容汇总 修复了任务栏在某些情况下无法正常显示的问题。 优化了系统的性能和稳定性。 解决了一些已知…

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