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

news2024/11/15 8:54:05

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代码,为项目的成功实施提供坚实的基础。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Shopee如何入驻?如何防封?

Shopee作为东南亚领航电商平台,面向东南亚蓝海市场,近年来随着东南亚市场蒸蒸日上,虾皮也吸引了大批量的跨境商家入驻。那么接下来就给想要入驻的虾皮小白一个详细的安全入驻教程。 一、商家如何入驻 虾皮与LAZADA最大的区别就是商家即卖家&…

RT-DETR改进 | 2023 | InnerEIoU、InnerSIoU、InnerWIoU、InnerDIoU等二十余种损失函数

论文地址:官方Inner-IoU论文地址点击即可跳转 官方代码地址:官方代码地址-官方只放出了两种结合方式CIoU、SIoU 本位改进地址: 文末提供完整代码块-包括InnerEIoU、InnerCIoU、InnerDIoU等七种结合方式和其AlphaIoU变种结合起来可以达到二十…

15、矩阵键盘密码锁

矩阵键盘密码锁 main.c #include <REGX52.H> #include "Delay.h" #include "LCD1602.h" #include "MatrixKey.h"//初始化变量 unsigned char KeyNum; unsigned int Password,Count;void main() {//LCD屏幕初始化显示Password:LCD_Init();…

kafka的详细安装部署

简介&#xff1a; Kafka是一个分布式流处理平台&#xff0c;主要用于处理高吞吐量的实时数据流。Kafka最初由LinkedIn公司开发&#xff0c;现在由Apache Software Foundation维护和开发。 Kafka的核心是一个分布式发布-订阅消息系统&#xff0c;它可以处理大量的消息流&#…

matplotlib,DLL load failed: 找不到指定的模块

问题&#xff1a;import matplotlib mportError: DLL load failed: 找不到指定的模块 &#xff08;2023年11月28日&#xff09; 解决方法&#xff1a;具体是matplotlib版本不匹配&#xff0c;而且在线pip install numpy时因为在线下载numpy库中缺少DLL。 应该下载带有mkl的num…

利用ogr2ogr从PostGIS中导出/导入Tab/Dxf/Geojson等格式数据

ogr2ogr Demo Command 先查看下当前gdal支持的全部格式&#xff0c;部分gdal版本可能不支持PostGIS。 如出现PostgreSQL表名支持。 #全部支持的格式 ogrinfo --formats | sort #AVCBin -vector- (rov): Arc/Info Binary Coverage #AVCE00 -vector- (rov): Arc/Info E00 (ASC…

居家适老化设计第三十三条---卫生间之暖风

居家适老化是指为了满足老年人居住需求而进行的住房改造&#xff0c;以提供更加安全、舒适、便利的居住环境。在居家适老化中&#xff0c;暖风系统是一个重要的考虑因素。暖风系统可以提供温暖舒适的室内温度&#xff0c;对老年人来说尤为重要。老年人常常身体机能下降&#xf…

PHPExcel 导出Excel报错:PHPExcel_IOFactory::load()

背景 近期在做 excel文件数据导出时&#xff0c;遇到如下报错&#xff1a; iconv(): Detected an illegal character in input string场景&#xff1a;计划任务后台&#xff0c;分步导出 大数据 excel文件发现在加载文件时&#xff0c;会有报错 报错信息 如下&#xff1a; {&q…

Elasticsearch初识--CentOS7安装ES及Kibana

文章目录 一&#xff0e;前言二&#xff0e;介绍1.Elasticsearch2.Kibana 三&#xff0e;ES安装1.下载安装包2.解压、配置2.1 解压2.2 配置 3.启动3.1增加用户3.2启动 4.解决资源分配太少问题5.启动成功 四&#xff0e;Kibana安装1.下载安装包2.解压、配置2.1 解压2.2 配置2.2 …

使用char.js 柱形方式显示 一年12个月的最高气温与最低气温

<!DOCTYPE html> <html> <head><title>气温图表</title><script src"https://cdn.jsdelivr.net/npm/chart.js"></script><style>#myChart{width:800px;height: 400px;}</style> </head> <body>&l…

SQL注入-数据库基础/SQL语法

目录 一&#xff0c;数据库概述 1.1 数据库 1.2 了解 ACID 理论 1.3 识别数据库 二&#xff0c;SQL 语法基础 三&#xff0c;SQL语句实例 3.1 SQL基础语句 3.2 SQL高级语句 四&#xff0c;基于SQL注入理解语法/函数 4.1 语法 4.2 函数 五&#xff0c;目录数据库info…

百度人工智能培训第一天笔记

参加了百度人工智能初步培训&#xff0c;主要是了解一下现在人工智能的基本情况&#xff0c;以便后续看可以参与一些啥&#xff1f; 下面就有关培训做一些记录&#xff0c;以便后续可以继续学习。 一、理论基础部分 二、实际操作部分 主要学习的百度人工智能平台如下&#xf…

C++学习之路(八)C++ 用Qt5实现一个工具箱(增加一个粘贴板记录管理功能)- 示例代码拆分讲解

昨天&#xff0c;我们用 Qt5 实现了一个小工具箱的雏形《C 实现简单的Qt界面&#xff08;消息弹框、按钮点击事件监听&#xff09;》&#xff0c;但是没什么实用价值。为了增加点作用&#xff0c;我们今天就为这个小工具箱增加第一个小功能 「 粘贴板记录管理功能 」&#xff0…

如何正确选择爬虫采集接口和API?区别在哪里?

在信息时代&#xff0c;数据已经成为了一个国家、一个企业、一个个人最宝贵的资源。而爬虫采集接口则是获取这些数据的重要手段之一。本文将从以下八个方面进行详细讨论&#xff1a; 1.什么是爬虫采集接口&#xff1f; 2.爬虫采集接口的作用和意义是什么&#xff1f; 3.爬虫…

数据可视化:在Jupyter中使用Matplotlib绘制常用图表

Matplotlib是一个强大的数据可视化库&#xff0c;用于创建各种图表。 在Jupyter中使用Matplotlib可以轻松实现折线图、柱状图、散点图和饼图等常用图表。 本篇文章将为你详细讲解用matlpotlib绘制常用图表的方法。 1、折线图 折线图是展示数据趋势和变化的常见图表类型。 …

【Proteus仿真】【51单片机】智能晾衣架设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真51单片机控制器&#xff0c;使用LCD1604液晶、按键、蜂鸣器、L298N电机、PCF8591 ADC模块、DHT11温湿度传感器、雨滴传感器、风速、光线传感器等。 主要功能&#xff1a; 系统运行…

负公差智能测径仪 升级体验智能仪器

负公差轧制离不开智能测径仪 受自动化控制程度限制&#xff0c;一些工艺流程的操作还是依靠工人经验来完成&#xff0c;由于个人工作技能水平限制&#xff0c;尺寸控制极不稳定&#xff0c;因此控制台就需要及时准确的了解成品钢的尺寸及重量。现在信息的沟通主要依靠电话。取样…

excel合并单元格教程

在表格里&#xff0c;总是会遇到一级表格、二级表格的区别&#xff0c;这时候一级表格会需要合并成一个大格子&#xff0c;那么excel如何合并单元格呢&#xff0c;其实使用快捷键或者功能键就可以了。 excel如何合并单元格&#xff1a; 1、首先我们用鼠标选中所有要合并的单元…

geemap学习笔记015:下载哨兵2号(Sentinel-2)数据

前言 使用GEE下载数据应该是最常见的功能了&#xff0c;今天就介绍一下如何使用geemap下载哨兵2号(Sentinel-2)数据&#xff0c;分别包括自己画感兴趣&#xff0c;以及利用Assets中的shp文件进行下载。 1 自己画感兴趣下载哨兵2号影像 import geemap import eeMap geemap.M…

北美区域性确定性预测系统平均温度数据

区域确定性预测系统&#xff08;RDPS&#xff09; 区域确定性预测系统 (RDPS) 进行物理计算&#xff0c;以 10.0 公里网格&#xff08;1/11 度&#xff09;空间分辨率对当天到未来 48 小时内的大气元素进行确定性预测。平均温度数据覆盖北美&#xff0c;由加拿大气象局 (MSC) …