从0开始学习JavaScript--JavaScript对象继承深度解析

JavaScript中的对象继承是构建灵活、可维护代码的关键部分。本文将深入讨论JavaScript中不同的继承方式,包括原型链继承、构造函数继承、组合继承等,并通过丰富的示例代码展示它们的应用和差异。通过详细解释,大家可以更全面地了解如何在JavaScript中有效地使用对象继承。

原型链继承

原型链继承是JavaScript中最基本的继承方式。这里将深入研究原型链是如何构建的,以及如何通过原型链使对象实现继承。

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

Animal.prototype.makeSound = function() {
  console.log('Some generic sound');
};

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

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
  console.log('Woof! Woof!');
};

const myDog = new Dog('Buddy', 'Golden Retriever');
myDog.makeSound(); // 继承自Animal
myDog.bark();      // Dog自有方法

构造函数继承

构造函数继承通过在子类构造函数内部调用父类构造函数来实现继承。这种方式避免了原型链继承的一些问题。

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

Animal.prototype.makeSound = function() {
  console.log('Some generic sound');
};

function Cat(name, color) {
  Animal.call(this, name);
  this.color = color;
}

const myCat = new Cat('Whiskers', 'Gray');
myCat.makeSound(); // Error: myCat.makeSound is not a function

组合继承

组合继承结合了原型链继承和构造函数继承的优点,是一种常用的继承方式。

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

Animal.prototype.makeSound = function() {
  console.log('Some generic sound');
};

function Horse(name, color) {
  Animal.call(this, name);
  this.color = color;
}

Horse.prototype = Object.create(Animal.prototype);
Horse.prototype.constructor = Horse;

const myHorse = new Horse('Spirit', 'Brown');
myHorse.makeSound(); // 继承自Animal

原型式继承

原型式继承通过借助现有对象创建新对象,是一种简单的继承方式。

const animal = {
  makeSound: function() {
    console.log('Some generic sound');
  }
};

const dog = Object.create(animal);
dog.bark = function() {
  console.log('Woof! Woof!');
};

dog.makeSound(); // 继承自animal
dog.bark();      // dog自有方法

寄生式继承

寄生式继承是在原型式继承的基础上增强对象,可以在对象上添加额外的方法。

function createDog(name) {
  const dog = Object.create({
    makeSound: function() {
      console.log('Some generic sound');
    }
  });
  dog.name = name;
  dog.bark = function() {
    console.log('Woof! Woof!');
  };
  return dog;
}

const myDog = createDog('Buddy');
myDog.makeSound(); // 继承自原型对象
myDog.bark();      // 自有方法

寄生组合式继承

寄生组合式继承是在组合继承的基础上进行优化,避免了调用两次父类构造函数。

function inheritPrototype(subType, superType) {
  const prototype = Object.create(superType.prototype);
  prototype.constructor = subType;
  subType.prototype = prototype;
}

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

Vehicle.prototype.drive = function() {
  console.log('Vroom!');
};

function Car(name, color) {
  Vehicle.call(this, name);
  this.color = color;
}

inheritPrototype(Car, Vehicle);

Car.prototype.honk = function() {
  console.log('Honk! Honk!');
};

const myCar = new Car('Toyota', 'Blue');
myCar.drive(); // 继承自Vehicle
myCar.honk();  // Car自有方法

ES6的Class继承

ES6引入了class语法糖,提供了更清晰、更面向对象的继承方式。

class Animal {
  constructor(name) {
    this.name = name;
  }

  makeSound() {
    console.log('Some generic sound');
  }
}

class Bird extends Animal {
  constructor(name, color) {
    super(name);
    this.color = color;
  }

  fly() {
    console.log('I believe I can fly!');
  }
}

const myBird = new Bird('Tweety', 'Yellow');
myBird.makeSound(); // 继承自Animal
myBird.fly();       // Bird自有方法

Symbol与继承

Symbol是ES6引入的一种新的原始数据类型,可以用于创建唯一的标识符。在继承中,Symbol可以用于创建不可枚举的属性。

const animal = {
  name: 'Generic Animal',
};

const key = Symbol('sound');
animal[key] = 'Some generic sound';

const dog = Object.create(animal);
dog.bark = function() {
  console.log(this[key]);
};

dog.bark(); // 继承自animal的Symbol属性

混入(Mixin)

混入是一种通过将多个对象的属性和方法合并到一个新对象中的方式,实现了对象的复用。

const canSwim = {
  swim() {
    console.log('Swimming!');
  },
};

const canFly = {
  fly() {
    console.log('Flying!');
  },
};

function mixin(target, ...sources) {
  Object.assign(target, ...sources);
}

const duck = {};
mixin(duck, canSwim, canFly);

duck.swim(); // 来自canSwim
duck.fly();  // 来自canFly

对象继承的性能考虑

在对象继承中,性能是一个重要的考虑因素。选择合适的继承方式可以显著影响代码的执行效率。以下是一些关于性能考虑的建议:

1. 原型链深度

过度的原型链深度会导致原型链查找时间增加,影响性能。尽量保持原型链的简洁,避免过多层次的嵌套。合理使用原型链,确保在维护性和性能之间找到平衡。

2. 构造函数调用

在构造函数继承中,避免不必要的构造函数调用。有些继承方式可能会多次调用父类的构造函数,造成冗余的工作。寻找可以减少构造函数调用次数的优化方法是很重要的。

3. 原型链查找与缓存

对于频繁访问的属性和方法,可以考虑将其缓存到子对象中,避免在原型链上进行多次查找。这可以通过在构造函数中引用父类的方法或属性来实现。

4. Class与原型链

在ES6中引入的class语法糖相比传统原型链继承具有更好的性能。它更直观,而且对引擎的优化更友好。在现代JavaScript开发中,推荐使用class语法糖来实现对象的继承。

5. 延迟加载

某些情况下,可以考虑延迟加载一些不常用的属性或方法,以提高初始加载性能。这可以通过在需要时动态加载相关部分来实现。

6. 使用原生方法

尽量使用原生方法,因为它们通常由JavaScript引擎进行高度优化。避免过度封装或使用过多的抽象层,以确保性能的最佳表现。

在实际项目中,性能优化往往需要根据具体情况进行调整。通过使用工具进行性能分析,可以更准确地找到需要优化的地方。综上所述,选择合适的继承方式并结合性能最佳实践,能够有效提升应用程序的整体性能。

总结

在深入探讨JavaScript对象继承的过程中,不仅理解了各种继承方式的实现机制和优缺点,而且关注了性能方面的考虑。对于性能,强调了避免过度的原型链深度、谨慎处理构造函数调用、合理使用原型链查找与缓存等策略。

了解继承方式的性能影响有助于开发者在实际应用中做出明智的选择。我们推崇使用ES6引入的class语法糖,因为它不仅直观易懂,还对JavaScript引擎的优化更为友好。此外,延迟加载和原生方法的使用也是提高性能的有效手段。

总体而言,通过深入研究JavaScript对象继承,能够更好地权衡继承方式的利弊,选择适合项目需求的方式。性能方面的考虑则为我们提供了优化代码的指导原则,确保我们在维护性和性能之间取得平衡。通过这些理念的应用,能够编写更高效、可维护的JavaScript代码,为项目的成功实施提供坚实的基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/194305.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vulfocus apache-cve_2021_41773 漏洞复现

vulfocus apache-cve_2021_41773 漏洞复现 名称: vulfocus/apache-cve_2021_41773 描述: Apache HTTP Server 2.4.49、2.4.50版本对路径规范化所做的更改中存在一个路径穿越漏洞,攻击者可利用该漏洞读取到Web目录外的其他文件,如系统配置文件、网站源码…

IDEA中也能用postman了?

Postman是大家最常用的API调试工具,那么有没有一种方法可以不用手动写入接口到Postman,即可进行接口调试操作?今天给大家推荐一款IDEA插件:Apipost Helper,写完代码就可以调试接口并一键生成接口文档!而且还…

修改mysql的密码(每一步都图文解释哦)

当你想要连接本机数据库时,是不是有可能突然忘记了自己的数据库密码? 在此文中,我们来详细解决一下如何去修改自己的数据库密码,并使用Navicat来连接测试 1.停止mysql服务 打开终端,键入命令,将mysql服务先停止掉,…

Matlab论文插图绘制模板第128期—函数三维折线图(fplot3)

在之前的文章中,分享了Matlab函数折线图的绘制模板: 进一步,再来分享一下函数三维折线图。 先来看一下成品效果: 特别提示:本期内容『数据代码』已上传资源群中,加群的朋友请自行下载。有需要的朋友可以关…

Linux系统编程:文件系统总结

目录和文件 获取文件属性 获取文件属性有如下的系统调用,下面逐个来分析。 stat:通过文件路径获取属性,面对符号链接文件时获取的是所指向的目标文件的属性 从上图中可以看到stat函数接收一个文件的路径字符串(你要获取哪个文件的属性&a…

数据结构和算法-树和二叉树的定义和基本术语和性质

文章目录 树的基本概念和相关术语相关的应用节点间的关系描述节点,树的属性描述有序树vs无序树树vs森林小结 树的相关性质考点1考点2考点3考点4考点5考点6小结 二叉树的相关概念和基本术语重要 (五种状态)特殊二叉树小结 二叉树的相关性质二叉…

SpringCloudAlibaba之Nacos的持久化和高可用——详细讲解

目录 一、Nacos持久化 1.持久化说明 2.安装mysql数据库5.6.5以上版本(略) 3.修改配置文件 二、nacos高可用 1.集群说明 2.nacos集群架构图 2.集群搭建注意事项 3.集群规划 4.搭建nacos集群 5.安装Nginx 6.配置nginx conf配置文件 7.启动nginx进行测试即可 一、Nacos持久…

【算法】NOIP2003神经网络

题目描述 人工神经网络(Artificial Neural Network)是一种新兴的具有自我学习能力的计算系统,在模式识别、函数逼近及贷款风险评估等诸多领域有广泛的应用。对神经网络的研究一直是当今的热门方向,兰兰同学在自学了一本神经网络的…

经验分享:JMeter控制RPS

一、前言 ​ RPS (Request Per Second)一般用来衡量服务端的吞吐量,相比于并发模式,更适合用来摸底服务端的性能。我们可以通过使用 JMeter 的常数吞吐量定时器来限制每个线程的RPS。对于RPS,我们可以把他理解为我们的TPS,我们就…

19.Oracle11g中的游标

oracle11g中的游标 一、案例引入二、什么是游标三、隐式游标1、隐式游标的属性2、创建语法3、示例 四、显示游标1、显示游标的属性2、创建语法3、示例 五、REF游标1、REF游标的属性2、创建语法3、示例 六、循环游标1、 循环游标的作用2、用for 与 loop 创建3、示例 一、案例引入…

基于可微分渲染器的相机位置优化【PyTorch3D】

在这个教程中,我们将使用可微渲染学习给定参考图像的相机的 [x, y, z] 位置。 我们将首先使用相机的起始位置初始化渲染器。 然后,我们将使用它来生成图像,使用参考图像计算损失,最后通过整个管道进行反向传播以更新相机的位置。…

【开源】基于Vue+SpringBoot的企业项目合同信息系统

项目编号: S 046 ,文末获取源码。 \color{red}{项目编号:S046,文末获取源码。} 项目编号:S046,文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 合同审批模块2.3 合…

Flask Echarts 实现历史图形查询

Flask前后端数据动态交互涉及用户界面与服务器之间的灵活数据传递。用户界面使用ECharts图形库实时渲染数据。它提供了丰富多彩、交互性强的图表和地图,能够在网页上直观、生动地展示数据。ECharts支持各种常见的图表类型,包括折线图、柱状图、饼图、散点…

FFmepg 核心开发库及重要数据结构与API

文章目录 前言一、FFmpeg 核心开发库二、FFmpeg 重要数据结构与 API1、简介2、FFmpeg 解码流程①、FFmpeg2.x 解码流程②、FFmpeg4.x 解码流程 3、FFMpeg 中比较重要的函数以及数据结构①、数据结构②、初始化函数③、音视频解码函数④、文件操作⑤、其他函数 三、FFmpeg 流程1…

【活动回顾】sCrypt在柏林B2029开发者周

B2029 是柏林的一个区块链爱好者、艺术家和建设者聚会,学习、讨论和共同构建比特币区块链地方。 在2023年6月9日至11日,举行了第7次Hello Metanet研讨会。本次研讨会旨在为参与者提供一个学习、讨论和共同构建比特币区块链的平台。 在这个充满激情和创意…

C语言:输出所有“水仙花数”。“水仙花数”是指一个3位数,其各位数字的立方和等于该数本身,如153=1^3 +5^3+3^3

分析: 在主函数 main 中,程序首先定义四个整型变量 m、a、b 和 c,并用于计算和判断水仙花数。然后使用 printf 函数输出提示信息。 接下来,程序使用 for 循环结构,从 100 到 999 遍历所有三位数。对于每个遍历到的数 m…

Vue简易的车牌输入键盘,可以根据需要修改

效果图如下&#xff1a; 代码如下&#xff1a; <template><div><div class"carNoBoxInput"><div style"padding: 6px;border: 2px solid #fff;border-radius: 6px;margin: 6px 3px 6px 6px;"><input class"inputBox"…

Make sure bypassing Vue built-in sanitization is safe here.

一、问题描述 二、问题分析 XSS(跨站脚本攻击) XSS攻击通常指的是通过利用网页开发时留下的漏洞&#xff0c;通过巧妙的方法注入恶意指令代码到网页&#xff0c;使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript&#xff0c;但实际上也可以包括J…

https到底把什么加密了?

首先直接说结论&#xff0c; https安全通信模式&#xff0c;是使用TLS加密传输所有的http协议。再重复一遍&#xff0c;是所有&#xff01; 通常将TLS加密传输http这个通信过程称为https&#xff0c;如果使用协议封装的逻辑结构来表达就是&#xff1a; IP TCP TLS 【 HTTP 】…

大连大学2023年11月程序设计竞赛(同步赛)

B、爆wa种子!&#xff08;数学&#xff09; 一、题目要求 链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 爆wa种子发现了上次玩游戏时你和妙wa种子的py交易&#xff0c;所以他要求这次玩游戏你来当爆wa种子的枪手&#xff0c;为他写个程序…