JS继承与原型、原型链
在 JavaScript 中,继承是实现代码复用和构建对象关系的重要概念。本文将讨论原型链继承、构造函数继承以及组合继承等几种常见的继承方式,并提供相应的示例代码,并分析它们的特点、优缺点以及适用场景。
在开始讲解 JavaScript 的继承方式之前,我们先来详细解释一下原型(prototype)、构造函数(constructor)和实例对象(instance)这三个概念。因为只有对它们有清晰的理解,才能更好地理解和应用JavaScript的继承机制。现在我们将分别介绍它们的含义和它们之间的关系。
建议点赞收藏本文章,以便日后复习~~
原型、构造函数、实例对象
在 JavaScript 中,原型(prototype)、构造函数(constructor)和实例对象(instance)是面向对象编程中的重要概念,并且它们之间存在着紧密的关系。
- 原型(prototype): 原型是JavaScript中对象之间关联的一种机制。每个JavaScript对象(除了 null 和 undefined)都有一个原型对象,它包含了对象的属性和方法。当我们访问一个对象的属性或方法时,如果对象本身没有定义该属性或方法,JavaScript引擎会通过原型链向上查找,直到找到对应的属性或方法为止。同理,原型链是由对象的原型对象构成的链式结构,通过这种机制,对象可以继承原型对象的属性和方法。
- 构造函数(constructor): 构造函数是用于创建对象的函数。在JavaScript中,我们可以通过定义一个函数并使用
new
关键字来创建对象的实例
。构造函数定义了对象的初始状态和行为,并且可以在创建实例时对其进行初始化。构造函数可以包含属性和方法,并且可以使用this
关键字引用要创建的实例对象。 - 实例对象(instance): 实例对象是通过构造函数创建的对象,它具有构造函数定义的属性和方法。每个实例对象都是独立的,它们可以根据需要修改自己的属性值,并且可以调用构造函数中定义的方法。实例对象通过原型链与构造函数的原型对象关联在一起,从而实现属性和方法的继承。
function Animal(name) { // 构造函数(自带原型对象)this.name = name || 'Animal'; // 属性
}Animal.prototype.eat = function(food) { // 方法console.log(this.name + '正在吃:' + food);
};var animal = new Animal('Tom'); // 实例对象animal.eat('猫粮')
它们之间的关系如下:
- 每个构造函数都有一个原型对象(prototype),构造函数的原型对象包含了构造函数定义的属性和方法。
- 通过构造函数创建的每个实例对象都有一个内部属性(Prototype),它指向构造函数的原型对象。这个属性在浏览器中通常可以通过
__proto__
访问(某些浏览器不支持)。 - 实例对象可以访问构造函数原型对象中的属性和方法。因为它们通过原型链与原型对象关联在一起,如果实例对象访问的属性或方法在自身中找不到,JavaScript引擎会自动沿着原型链向上查找,直到找到对应的属性或方法。
- 当我们修改实例对象的属性时,它会在自身中创建一个与原型对象中同名属性的副本,并在之后的访问中直接使用该副本,而不会影响原型对象中的属性。
- 当我们调用实例对象的方法时,JavaScript引擎会优先在实例对象中查找对应的方法,如果找不到则会继续沿着原型链向上查找,直到找到对应的方法。
什么是JavaScript继承
JavaScript继承是指在前端开发中,使用JavaScript实现对象之间属性和方法的继承关系。继承是面向对象编程的重要概念,它允许我们创建基于现有对象的新对象,并在新对象中拥有原有对象的属性和方法。
在JavaScript中,继承是通过原型链来实现的。每个对象都有一个原型对象,它包含对象的属性和方法。当我们访问一个对象的属性或方法时,如果对象本身没有定义该属性或方法,JavaScript引擎会通过原型链向上查找,直到找到对应的属性或方法为止。这种原型链的查找机制使得对象之间可以共享属性和方法,从而实现继承的效果。
除了原型链继承外,JavaScript还提供了其他几种实现继承的方式,如构造函数继承、组合继承等。在开发中,继承通常用于构建对象之间的关系,使得子类可以共享父类的属性和方法,并有能力添加自己的特定属性和方法。这样可以减少重复的代码编写,提高开发效率和代码的可维护性。
接下来我们详细介绍这些继承方式的原理和使用方法,并提供相应的代码示例。
JavaScript继承方式
1、原型链继承
原型链继承是一种基于原型的继承方式,它通过将父类的实例作为子类的原型来实现继承关系。具体实现如下:
function Animal(name) {this.name = name || 'Animal';
}Animal.prototype.eat = function(food) {console.log(this.name + '正在吃:' + food);
};function Cat() {Animal.call(this);
}Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
Cat.prototype.name = 'Tom';var cat = new Cat();
原型链继承的特点包括:
- 实例既是子类的实例,也是父类的实例,继承关系非常纯粹。
- 子类可以访问父类新增的原型方法和属性。
- 实现简单,易于理解和实现。
原型链继承的缺点:
- 子类无法在构造器中新增属性和方法,只能在实例化后添加。
- 无法实现多继承。
- 所有实例共享来自原型对象的属性,包括引用属性。
原型链继承适用于简单的继承关系和单一继承需求的场景。
2、构造继承
构造继承通过在子类构造函数中调用父类构造函数,复制父类的实例属性给子类。具体实现如下:
function Animal(name) {this.name = name || 'Animal';
}Animal.prototype.eat = function(food) {console.log(this.name + '正在吃:' + food);
};function Cat(name) {Animal.call(this, name);
}var cat = new Cat();
构造继承的特点包括:
- 解决了原型链继承中子类实例共享父类引用属性的问题。
- 可以在创建子类实例时向父类传递参数。
- 支持多继承,可以调用多个父类构造函数。
构造继承的缺点:
- 子类实例并不是父类的实例,只是子类的实例。
- 无法继承父类的原型属性和方法。
- 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能。
构造继承适用于需要继承实例属性、避免引用属性共享以及多继承的场景。
3、实例继承
实例继承通过为父类实例添加新特性,并将其作为子类实例返回。具体实现如下:
function Animal(name) {this.name = name || 'Animal';
}Animal.prototype.eat = function(food) {console.log(this.name + '正在吃:' + food);
};function Cat(name) {var instance = new Animal();instance.name = name || 'Tom';return instance;
}var cat = new Cat();
实例继承的特点包括:
- 不限制调用方式,无论是
new 子类()
还是子类()
,返回的对象具有相同的效果。
实例继承的缺点:
- 实例是父类的实例,而不是子类的实例。
- 不支持多继承。
实例继承适用于灵活的对象创建需求,可以根据不同情况返回不同的实例。
4、拷贝继承
拷贝继承通过复制父类的属性和方法给子类实现继承。具体实现如下:
function Animal(name) {this.name = name || 'Animal';
}Animal.prototype.eat = function(food) {console.log(this.name + '正在吃:' + food);
};function Cat(name) {Animal.call(this, name);
}for (var p in Animal.prototype) {if (Animal.prototype.hasOwnProperty(p)) {Cat.prototype[p] = Animal.prototype[p];}
}Cat.prototype.constructor = Cat;
var cat = new Cat();
拷贝继承的特点包括:
- 支持多继承。
拷贝继承的缺点:
- 效率较低,内存占用高,因为需要拷贝父类的属性。
- 无法获取父类的不可枚举方法。
拷贝继承适用于多继承的场景,但要注意性能和不可枚举方法的问题。
5、组合继承(原型继承+构造继承)
组合继承结合了原型继承和构造继承的优点,通过调用父类构造函数来继承父类的属性,并将父类实例作为子类原型,实现函数复用。具体实现如下:
function Animal(name) {this.name = name || 'Animal';
}Animal.prototype.eat = function(food) {console.log(this.name + '正在吃:' + food);
};function Cat(name) {Animal.call(this, name);
}Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;var cat = new Cat();
组合继承的特点包括:
- 继承父类实例属性和方法。
- 继承父类原型属性和方法。
- 既是父类的实例,也是子类的实例。
组合继承的缺点:
- 调用了两次父类构造函数,影响性能。
组合继承适用于大多数场景,是一种常用的继承方式。
6、寄生组合继承
寄生组合继承是对组合继承的优化,通过寄生方式避免了两次调用父类构造函数,从而减少了实例化时的重复操作。具体实现如下:
function Animal(name) {this.name = name || 'Animal';
}Animal.prototype.eat = function(food) {console.log(this.name + '正在吃:' + food);
};function Cat(name) {Animal.call(this, name);
}function inheritPrototype(subType, superType) {var prototype = Object.create(superType.prototype);prototype.constructor = subType;subType.prototype = prototype;
}inheritPrototype(Cat, Animal);var cat = new Cat();
寄生组合继承的特点包括:
- 实现简单,堪称完美。
寄生组合继承没有明显的缺点,是一种高效且可靠的继承方式。
结语
我们可以根据具体需求选择适合的继承方式。每种继承方式都有自己的优缺点和适用场景,因此我们应根据实际情况进行选择和灵活运用。
相关文章:

JS继承与原型、原型链
在 JavaScript 中,继承是实现代码复用和构建对象关系的重要概念。本文将讨论原型链继承、构造函数继承以及组合继承等几种常见的继承方式,并提供相应的示例代码,并分析它们的特点、优缺点以及适用场景。 在开始讲解 JavaScript 的继承方式之…...

C#基础知识总结
C语言、C和C#的区别 ✔ 面向对象编程(OOP): C 是一种过程化的编程语言,它不直接支持面向对象编程。然而,C 是一种支持 OOP 的 C 的超集,它引入了类、对象、继承、多态等概念。C# 是完全面向对象的ÿ…...
机器学习模型——决策树
决策树的定义: 决策树利用树形数据结构来展示决策规则和分类结果,它是一种归纳学习算法,可以将复杂数据转化为可以预测未知数据的模型。每一条从根节点到叶节点的路径都代表一条决策规则。 决策树内的一些重要名词: 信息熵&am…...

【HTML】制作一个简单的三角形动态图形
目录 前言 开始 HTML部分 CSS部分 效果图 总结 前言 无需多言,本文将详细介绍一段HTML和CSS代码,具体内容如下: 开始 首先新建文件夹,创建两个文本文档,其中HTML的文件名改为[index.html],CSS的文件名…...
Acwing.504 转圈游戏(带取余的快速幂)
题目 n个小伙伴(编号从 0到 n−1)围坐一圈玩游戏。 按照顺时针方向给 n个位置编号,从 0到 n−1。 最初,第 0号小伙伴在第 0号位置,第 1号小伙伴在第 1号位置,…,依此类推。 游戏规…...
pair作为unordered_map的key报错
问题 pair作为unordered_map的key报错,编译时会报错 原因 因为pair没有哈希函数 解决方法 定义哈希函数 template <typename T> inline void hash_combine(std::size_t &seed, const T &val) {seed ^ std::hash<T>()(val) 0x9e3779b9 (…...

Windows提权—数据库提权-mysql提权mssql提权Oracle数据库提权
目录 Windows 提权—数据库提权一、mysql提权1.1 udf提权1.1.2 操作方法一 、MSF自动化--UDF提权--漏洞利用1.1.3 操作方法二、 手工导出sqlmap中的dll1.1.4 操作方法三、 moon.php大马利用 1.2 mof提权1.3 启动项提权1.4 反弹shell 二、MSSQL提权MSSQL提权方法1.使用xp_cmdshe…...
为什么android创建Fragment推荐用newInstance
FullScreenDialogFragment使用newInstance方法不是因为它是一个单例,而是因为这是创建DialogFragment实例并同时提供参数的一种标准模式。这种模式通常称为静态工厂方法模式,在Android开发中被广泛使用,尤其是用于Fragment的实例化。 newIns…...

MyBatis的xml实现方式
1、该项目引入的依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.o…...

大模型prompt技巧——思维链(Chain-of-Thought)
1、Zero-shot、One-shot、Few-shot 与fintune prompt的时候给出例子答案,然后再让模型回答。 2、zero-shot-CoT “Let’s think step by step”有奇迹效果 3、多数投票提高CoT性能——自洽性(Self-consistency) 多个思维链,然后取…...

内网穿透的应用-如何在Android Termux上部署MySQL数据库并实现无公网IP远程访问
文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备,尽管最初并非设计为服务器,但是随着技术的进步我们可以将Android配置为生产力工具,变成一个随身…...
面试算法-133-区间子数组个数
题目 给你一个整数数组 nums 和两个整数:left 及 right 。找出 nums 中连续、非空且其中最大元素在范围 [left, right] 内的子数组,并返回满足条件的子数组的个数。 生成的测试用例保证结果符合 32-bit 整数范围。 示例 1: 输入ÿ…...

物联网实战--入门篇之(八)嵌入式-空气净化器
目录 一、风扇调速 二、通讯协议 三、净化器运行逻辑 一、风扇调速 单片机是不能直接驱动电机的,因为主芯片的驱动电流比较小(50mA左右),他们之间正常还要有个电机驱动器,常用的有TB6612、L298和L9110等,目前项目用的这个电机它…...
macOS上QT打开麦克风和摄像头的权限问题
同样的代码在Windows上可以轻松操作麦克风和摄像头,特别是用QT这种跨平台的框架。但是对macOS这种权限要求完善的系统还需要进行一些配置,那就是增加Info.plist属性配置文件。如果是之前的早期5.x版本的QTCreator因为使用的是qmake构建系统,估…...

鸿蒙手机cordova-plugin-camera不能拍照和图片不显示问题
鸿蒙手机cordova-plugin-camera不能拍照和图片不显示问题 一、运行环境 1、硬件 手机型号:NOVA 7 系统:HarmonyOS版本 4.0.0 2、软件 android SDK platforms:14.0(API Level 34)、13.0(API Level 33) SDK Build-T…...

Spring源码解析上
spring源码解析 整体架构 defaultListableBeanFactory xmlBeanDefinitionReader 创建XmlBeanFactory 对资源文件进行加载–Resource 利用LoadBeandefinitions(resource)方法加载配置中的bean loadBeandefinitions加载步骤 doLoadBeanDefinition xml配置模式 validationMode 获…...
第九题:最大间隙
题目描述 给定一个序列 a1,a2,⋯ ,an。其中 a1≤a2≤⋯≤an。 相邻两个数之间的差(后一个数减前一个数)称为它们的间隙。 请问序列中最大的间隙值是多少? 输入描述 输入的第一行包含一个整数 n,表示序列的长度。 第二行包含…...

【随笔】Git -- 高级命令(中篇)(七)
💌 所属专栏:【Git】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! 💖 欢迎大…...

可视化大屏 - 项目1
文章目录 技术栈echarts 可视化需求分析代码实现 技术栈 flexible.js rem 实现不同终端下的响应式布局,根据不同屏幕宽度,自适配布局; html中引入index.js,可以改名为flexible.js;默认划分10份,可以自己修…...

Collection与数据结构 链表与LinkedList(三):链表精选OJ例题(下)
1. 分割链表 OJ链接 class Solution {public ListNode partition(ListNode head, int x) {if(head null){return null;//空链表的情况}ListNode cur head;ListNode formerhead null;ListNode formerend null;ListNode latterhead null;ListNode latterend null;//定义…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...

Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...