js原型、原型链和继承
文章目录
- 一、原型
- 1、prototype
- 2、constructor
- 二、原型链
- 1、字面量原型链
- 2、字面量继承
- 3、构造函数的原型链
- 4、Object.create
- 5、Object.setPrototypeOf
- 三、继承
- 1、构造函数继承
- 2、原型链继承
- 3、组合继承
- 四、常见链条
- 1、Function
- 2、Object.prototype
继承是指将特性从父代传递给子代,以便新代码可以重用并基于现有代码的特性进行构建。JavaScript 使用对象实现继承。每个对象都有一条链接到另一个称作原型的对象的内部链。该原型对象有自己的原型,依此类推,直到原型是 null 的对象。
一、原型
1、prototype
- 构造函数自带原型对象
prototype
,可以在prototype增加属性和方法,这样构造函数产生的实例可以共享这些属性和方法(如果实例上没有的话)- 实例
__proto__
属性指向最近的上级prototype(如果有继承),如果没有继承那么指向构造函数的prototype;__proto__在浏览器上显示的是[[Prototype]]
- 注意原型对象prototype也是对象,他是被Object创建出来的
const ParentFun = function () {this.name = "张三";
};
ParentFun.prototype.getName = function () {return this.name;
};
const parentObj = new ParentFun();
parentObj.__proto__ === ParentFun.prototype // true
2、constructor
constructor
其实依赖于prototype,只是prototype上的一个属性,指向构造函数本身(函数对象,函数也可以被认为是一个对象,可以挂载属性和方法)- 在原型链继承的时候,错误操作可能只顾着继承prototype,而丢失constructor属性
instanceof
: a instanceof b会在链条往上查找prototype.constructor,看a的原型链上有没有b;逐级上查
const ParentFun = function () {this.name = "张三";
};
ParentFun.prototype.constructor === ParentFun // true
// 等同于;因为ParentFunObj默认往上查找一层就是ParentFun.prototype
ParentFunObj.constructor === ParentFun // trueconst ParentFunObj = new ParentFun();
ParentFunObj instanceof ParentFun // true
ParentFunObj instanceof Object // true
二、原型链
1、字面量原型链
- 注意对象中设置字面量{ proto: … },是被允许的、合理的;不合理是设置隐式原型obj.proto = …
const obj = {a: 1,// __proto__ 设置了 [[Prototype]]。在这里它被指定为另一个对象字面量。__proto__: {b: 2,__proto__: {c: 3,},},
};
obj.a // 1
obj.b // 2
obj.c // 3
2、字面量继承
const parent = {value: 2,method() {return this.value + 1;}
};// child 是一个继承了 parent 的对象
const child = {__proto__: parent
};console.log(child.method()); // 3// child ---> parent ---> Object.prototype ---> null
3、构造函数的原型链
function Constructor() {}const obj = new Constructor();// obj ---> Constructor.prototype ---> Object.prototype ---> null
4、Object.create
const a = { a: 1 };
// a ---> Object.prototype ---> nullconst b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1(继承的)
5、Object.setPrototypeOf
const obj = { a: 1 };
const anotherObj = { b: 2 };
Object.setPrototypeOf(obj, anotherObj);
// obj ---> anotherObj ---> Object.prototype ---> null
三、继承
1、构造函数继承
- call、apply都可以
- 也可以使用class,本文案例未举例
const ParentFun = function () {this.name = "张三";
};
const ChildFun = function () {// 继承父类的属性和方法;构造函数继承;// 注意调用的时机,会决定实例的属性顺序;比如这里的name属性在age前面ParentFun.call(this);// 运行时this指向childFunc实例对象(的内存空间);this.age = 20;
};
2、原型链继承
Object.setPrototypeOf(ChildFun.prototype, ParentFun.prototype)
:给目标设置原型链的上一级;Object.setPrototypeOf(ChildFun.prototype)
:获取该目标的原型链的上一级Object.create(ParentFun.prototype)
:创建和返回新对象,设置该对象的原型链上一级- 原型链扩充,每次扩充都会形成上级和下级的二元链;链条可以被设置成连续不断一直到顶层null,也可以设置成短链
const ParentFun = function () {this.name = "张三";
};
const ChildFun = function () {// 继承父类的属性和方法;构造函数继承;// 注意调用的时机,会决定实例的属性顺序;比如这里的name属性在age前面ParentFun.call(this);// 运行时this指向childFunc实例对象(的内存空间);this.age = 20;
};
ParentFun.prototype.getName = function () {return this.name;
};
ChildFun.prototype.getAge = function () {return this.age;
};const transferTemp = (Parent, Child) => {// 空的对象作为临时原型链;const Temp = () => {};Temp.prototype = Parent.prototype;Child.prototype = new Temp();Child.prototype.constructor = Child;
};const transferCreat = (Parent, Child) => {// Object.create本身就会返回一个空对象,该对象的__proto__指向Parent.prototype;Child.prototype = Object.create(Parent.prototype);// 覆盖prototype以后会丢失constructor,需要重新赋值;// constructor在一些判断中可能被用到// prototype在此之前设置的其他属性也会消失(比如getAge)Child.prototype.constructor = Child;
};// 注意原型链继承方式的区别
// 1
// ChildFun.prototype = new ParentFun();
// 2 废弃但可用;__proto__ 赋值只会接受对象,其他值会被忽略
// ChildFun.prototype.__proto__ = ParentFun.prototype;
// 3 推荐 安全有效,没有中转对象
// Object.setPrototypeOf(ChildFun.prototype, ParentFun.prototype);
// 4 使用中转对象
// transferTemp(ParentFun, ChildFun);
// 5 使用中转对象
// transferCreat(ParentFun, ChildFun);
3、组合继承
const ParentFun = function () {this.name = "张三";
};
const ChildFun = function () {// 继承父类的属性和方法;构造函数继承;// 注意调用的时机,会决定实例的属性顺序;比如这里的name属性在age前面ParentFun.call(this);// 运行时this指向childFunc实例对象(的内存空间);this.age = 20;
};
ParentFun.prototype.getName = function () {return this.name;
};
ChildFun.prototype.getAge = function () {return this.age;
};// 自定义Object.keys方法 用于获取对象所有属性名
Object.prototype.keysCustom = function (obj) {if (typeof obj !== "object" || obj === null) {return;}const result = []; // 用于存储结果for (let key in obj) {// hasOwnProperty表示自身的属性,不包括原型链上的属性if (obj.hasOwnProperty(key)) {// 相当于循环后存储keyresult.push(key);}}return result;
};Object.setPrototypeOf(ChildFun.prototype, ParentFun.prototype);const childObj = new ChildFun();const keysAll = [];
const keysOwn = [];
for (let key in childObj) {// 自己的属性和原型链上的属性都会遍历出来;// 原型链继承的所有属性 + Object.prototype 挂载的自定义方法keysAll.push(key);if (childObj.hasOwnProperty(key)) {// 自己的属性才会遍历出来;keysOwn.push(key);}
}
// console.log("Object.keysCustom", keysAll, keysOwn, childObj); // TEST
// 结果:keysAll = ["name", "age", "getName", "keysCustom"];
// 结果: keysOwn = ["name", "age"];// childObj ---> ChildFun.prototype ---> ParentFun.prototype ---> Object.prototype ---> null
四、常见链条
1、Function
- Function是所有常见构造函数的源头,甚至他自己也被自己创造
- 只要是构造函数都归Function管理,包括自定义的函数
// Function创造自己
Object.getPrototypeOf(Function) === Function.prototype // true
// 常规构造函数
Object.getPrototypeOf(Object) === Function.prototype // true
Object.getPrototypeOf(Array) === Function.prototype // true
// 自定义构造函数
const temp =() => {}
Object.getPrototypeOf(temp) === Function.prototype // true
2、Object.prototype
- 只要是对象都归Object管理,包括prototype对象,当然有例外:Object.prototype
// 常规构造函数的prototype;上一级就是Object.prototype
Object.getPrototypeOf(Function.prototype) === Object.prototype // true
Object.getPrototypeOf(Array.prototype) === Object.prototype // true
// 链条顶层被null强制了
Object.getPrototypeOf(Object.prototype) === Object.prototype // false
Object.getPrototypeOf(Object.prototype) === null // true
相关文章:
js原型、原型链和继承
文章目录 一、原型1、prototype2、constructor 二、原型链1、字面量原型链2、字面量继承3、构造函数的原型链4、Object.create5、Object.setPrototypeOf 三、继承1、构造函数继承2、原型链继承3、组合继承 四、常见链条1、Function2、Object.prototype 继承是指将特性从父代传递…...
团队自创【国王的魔镜-2】
国王的魔镜-2 题目描述 国王有一个魔镜,可以把任何接触镜面的东西变成原来的两倍——只是,因为是镜子嘛,增加的那部分是反的。比如一条项链,我们用AB来表示,不同的字母表示不同颜色的珍珠。如果把B端接触镜面的话&am…...
c++编程玩转物联网:使用芯片控制8个LED实现流水灯技术分享
在嵌入式系统中,有限的GPIO引脚往往限制了硬件扩展能力。74HC595N芯片是一种常用的移位寄存器,通过串行输入和并行输出扩展GPIO数量。本项目利用树莓派Pico开发板与74HC595N芯片,驱动8个LED实现流水灯效果。本文详细解析项目硬件连接、代码实…...
【Jenkins】docker 部署 Jenkins 踩坑笔记
文章目录 1. docker pull 超时2. 初始化找不到 initialAdminPassword 1. docker pull 超时 docker pull 命令拉不下来 docker pull jenkins/jenkins:lts-jdk17 Error response from daemon: Get "https://registry-1.docker.io/v2/": 编辑docker配置 sudo mkdir -…...
Unreal Engine使用Groom 打包后报错
Unreal Engine使用Groom打包后报错 版本5.4.4 blender 4.2.1 项目头发用了groom,运行后报错 错误: Assertion failed: Offset BytesToRead < UncompressedFileSize && Offset > 0 [File:E:\UnrealEngine-5.4.4-release\Engine\Source\R…...
嵌入式QT学习第3天:UI设计器的简单使用
Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 Qt Creator 里自带的 Qt Designer,使用 Qt Designer 比较方便的构造 UI 界 面。 在 UI 文件添加一个按钮 左边找到 Push Button,然后拖拽到中…...
【连接池】.NET开源 ORM 框架 SqlSugar 系列
.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…...
图论入门编程
卡码网刷题链接:98. 所有可达路径 一、题目简述 二、编程demo 方法①邻接矩阵 from collections import defaultdict #简历邻接矩阵 def build_graph(): n, m map(int,input().split()) graph [[0 for _ in range(n1)] for _ in range(n1)]for _ in range(m): …...
在Java中使用Apache POI导入导出Excel(三)
本文将继续介绍POI的使用,上接在Java中使用Apache POI导入导出Excel(二) 使用Apache POI组件操作Excel(三) 24、拆分和冻结窗格 您可以创建两种类型的窗格;冻结窗格和拆分窗格。 冻结窗格按列和行进行拆分。您创建…...
UR开始打中国牌,重磅发布国产化协作机器人UR7e 和 UR12e
近日,优傲(UR)机器人公司立足中国市场需求,重磅推出UR7e和UR12e 两款本地化协作机器人。它们延续优傲(UR)一以贯之的高品质与性能特质,着重优化负载自重比,且在价格层面具竞争力&…...
FRU文件
FRU(Field Replaceable Unit)源文件的格式通常遵循IPMI FRU Information Storage Definition标准。在实际应用中,FRU源文件可以是JSON格式的,这种格式允许用户指定所有的FRU信息字段。以下是FRU源文件的JSON格式的一些关键点&…...
AI需求条目化全面升级!支持多格式需求,打破模板限制!
AI需求条目化全面升级!支持多格式需求,打破模板限制! 一、多格兼济 标准立成 1、功能揭秘 预览未来 平台需求板块的AI需求条目化功能迎来全面升级。它支持多种需求格式,不再受限于模板文件,能够一键自动快速且灵活地生…...
Java—I/O流
Java的I/O流(输入/输出流)是用于在程序和外部资源(如文件、网络连接等)之间进行数据交换的机制。通过I/O流,可以实现从外部资源读取数据(输入流)或将数据写入外部资源(输出流&#x…...
Huginn服务部署
工作中需要使用爬虫系统,做为技术选型需要对Huginn系统进行部署并进行功能验证。下面的文章会记录了Huginn的部署过程,本次部署采用的Ubuntu-23.0.4系统,使用Docker部署。部署过程需要翻墙。 一、安装Docker 删除旧版本 sudo apt-get remo…...
深入解析Java数据包装类型:特性、机制与最佳实践
文章目录 1. 基本概念2. 自动装箱与拆箱3. 缓存机制4. 不可变性5. 常见陷阱与最佳实践a. 空指针异常b. 不要用 比较两个包装类实例c. 高精度计算d. 字符串解析 总结 1. 基本概念 Java提供了每个基本数据类型的包装类,位于java.lang包中。这些包装类允许我们将基本…...
【Java基础入门篇】二、控制语句和递归算法
Java基础入门篇 二、控制语句和递归算法 2.1 switch-case多分支选择语句 switch执行case语句块时,若没有遇到break,则运行下一个case直到遇到break,最后的default表示当没有case与之匹配时,默认执行的内容,代码示例如…...
PostgreSQL WAL日志膨胀处理
作者:Digital Observer(施嘉伟) Oracle ACE Pro: Database PostgreSQL ACE Partner 11年数据库行业经验,现主要从事数据库服务工作 拥有Oracle OCM、DB2 10.1 Fundamentals、MySQL 8.0 OCP、WebLogic 12c OCA、KCP、PCTP、PCSD、P…...
用户该怎么管理维护自己的服务器?
管理和维护自己的服务器是确保其长期稳定、高效和安全运行的重要任务。以下是一些关键的服务器管理和维护的步骤和建议,适用于Linux或Windows服务器。 1.定期备份数据 定期备份是防止数据丢失和恢复故障的关键步骤。备份策略应包括: 全量备份:…...
【MYSQL数据库相关知识介绍】
MySQL 在我们日常技术中是一个广泛使用的开源关系型数据库管理系统,所以作为测试同学,掌握mysql的相关知识是必不可少的技能之一,所以小编从软件测试的角色出发,来整理一些跟测试相关的知识,希望能够帮助到大家。 一、…...
初窥 HTTP 缓存
引言 对于前端来说, 你肯定听说过 HTTP 缓存。 当然不管你知不知道它, 对于提高网站性能和用户体验, 它都扮演着重要的角色! 它通过在客户端和服务器之间存储和重用先前获取的资源副本, 来减少网络流量和降低资源加载时间, 从而提升用户体验! 以下是 HTTP 缓存的重要性: 减少…...
yolov8的深度学习环境安装(cuda12.4、ubuntu22.04)
目录 一、先安装基础环境包 1.首先给Ubuntu安装Chrome浏览器(搜索引擎换成百度即可) 2、ubuntu 22.04中文输入法安装 3、安装 terminator 4、安装WPS for Linux 5、安装其它之前需要先安装anaconda 6、安装配置anaconda 7、安装完成anaconda后创建…...
RSA算法和AES算法,哪种更安全
目录 一、RSA (非对称加密算法) 二、AES (对称加密算法) 三、对比总结 四、更安全的选择 五、结合使用:RSA AES RSA 和 AES 是两种不同类型的加密算法,适用于不同的场景,因此它们的安全性不能直接比较,而是取决于具体的应用…...
Vue教程|搭建vue项目|Vue-CLI新版脚手架
一、安装Node环境 安装Node及Npm环境 Node下载地址:Node.js — Run JavaScript EverywhereNode.js is a JavaScript runtime built on Chromes V8 JavaScript engine.https://nodejs.org/en/ 安装完成后,检查安装是否成功,并检查版本,命令如下: node -v npm -v mac@Macd…...
kdump调试分析(适用于麒麟,ubuntu等OS)
1. kdump基本原理 1.1 内核崩溃处理机制 当 Linux 系统内核发生崩溃时,通常会触发 panic,系统停止正常运行。Kdump 在这种情况下: 使用一个备用的内核(称为 crash kernel)来启动最小化的环境。从崩溃的主内核中复制内存内容(转储文件)。将转储文件保存到预定义的存储位…...
houdini肌肉刷pin点的方法
目标:产生gluetoanimation这个属性 主要节点:attribute paint(或者muscle paint) 步骤1: 导入肌肉资产 导入的是rest shape的肌肉 在有侧边栏可以打开display group and attribute list,方便查看group。不同的肌肉块按照muscl…...
JMeter 并发策略-针对准点秒杀场景的压测实现
一、场景的压测实现 1,创建线程组,10并发用户执行5次; 2,创建 Synchronizing Timer 元件,用于同步线程,设置同步元件 Synchronizing Timer 3,创建 http 请求4,创建 view results in table 元件…...
龙迅#LT6912适用于HDMI2.0转HDMI+LVDS/MIPI,分辨率高达4K60HZ,支持音频和HDCP2.2
1. 描述 LT6912是一款高性能的HDMI2.0转HDMI和LVDS和MIPI转换器。 HDMI2.0 输入和输出均支持高达 6Gbps 的数据速率,为4k60Hz视频提供足够的带宽。此外,还支持 HDCP2.2 进行数据解密(无数据 加密)。 对于 LVDS 输出,…...
RBF神经网络预测结合NSGAII多目标优化
目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 RBF神经网络预测结合NSGAII多目标优化 rbf神经网络预测结合nsga2多目标优化 题外话: 多目标优化是指在优化问题中同时考虑多个目标函数的优化过程。在多目标优化中,通常存在多个冲突的目标&am…...
如何看linux系统内核是aarch64 ,还是64-bit
要查看 Linux 系统内核是 aarch64 架构还是 64-bit 架构,可以通过以下几种方法来确认: 方法 1:使用 uname 命令 uname 命令用于显示系统信息。使用以下命令查看系统的架构: uname -m如果输出是 aarch64,说明你的系统…...
如何通过 ADB 安装 xapk
Android开发这么久,今天发现还能这么操作!😂 记录通过ADB安装xapk、apks的两种方式: 1.ADB命令安装使用APK-Splits技术分包的应用程序 这位大佬的方式步骤较为繁琐,不过兼容性应该较好,亲测成功安装。 2.How to install xapk, apks, or multiple-apks via adb? 这个…...
网络营销类型有哪些/seo推广策略
#define UsartRxBuffAddressArmEntry 0X20001000 #define UsartRxBuffSize 0x400 unsigned char USART_RX_BUF[UsartRxBuffSize ] __ attribute __((at(UsartBuffAddressArmEntry ))); //将串口接收的数据定位存放到RAM中地址为0X20001000–0x200013FF 中; #defin…...
品牌全案策划案例/上海谷歌seo
1、类加载机制 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制。 2、类加载的时机 类从被加载到虚拟机内存中开始,到卸载出…...
重庆怎么做网站?/b站推广入口
Oracle 常用初始化命令--创建一个表空间CREATE TABLESPACE MYSPACE DATAFILE D:/MYSPACE.DBF SIZE 10M AUTOEXTEND ON--指定某个用户的默认的表空间是MYSPACEALTER USER SYSTEM IDENTIFIED BY NIIT DEFAULT TABLESPACE MYSPACE QUOTA UNLIMITED ON MYSPACECOMMIT--删除表空间DR…...
好用的wordpress企业模版/百度官网下载
一个项目只有一给仓库,状态也只能有一个,但是组件会非常之多,我们为了每个组件的共享状态便于统一管理,需要将多个reducer进行合并 export default function combineReducers(reducers) {const reducerKeys Object.keys(reducer…...
哪里有专业网站建设公司/互联网推广引流公司
天线辐射电磁波的原理 1.天线的作用 导线载有交变电流时,就会辐射电磁波,其辐射能力与导线的长短和形状有关。若两导线的距离很近,电场被束缚在两导线之间,因而辐射很微弱;将两导线张开,电场就散播在周围空…...
小程序怎么放在桌面/天津网站建设优化
下面是我的github,首页后面的教程按照这个来的。https://github.com/wangsrGit119github.com创建同用户名仓库看下图,就是我的用户名同名仓库创建过程,因为之前创建了的所以提示已存在注意点:1.勾选public 2.勾选 Initialize th…...