javascript中原型链(__proto__)与原型(prototype)
JavaScript中原型链(proto)与原型(prototype)
在JavaScript中,理解原型链(__proto__)和原型(prototype)对于深入掌握面向对象编程至关重要。本文将通过示例代码,详细解析__proto__和prototype之间的关系,以及它们在对象和构造函数之间的作用。
一、基本概念
1. 构造函数与实例对象
- 构造函数:在JavaScript中,函数可以作为构造函数使用,通过
new关键字创建实例对象。 - 实例对象:由构造函数创建的对象,继承了构造函数的属性和方法。
2. 原型(prototype)
- prototype:每个函数(包括构造函数)都有一个
prototype属性,指向一个对象,这个对象被称为原型对象。 - 原型对象:存储共享的属性和方法,供所有实例对象访问。
3. 原型链(__proto__)
- proto:每个对象都有一个
__proto__属性,指向创建该对象的构造函数的原型对象。 - 原型链:通过
__proto__属性,将对象、构造函数和原型对象连接起来,形成一个链式结构。
二、示例代码解析
下面通过一段示例代码,逐步解析__proto__和prototype之间的关系。
function Person(name, age){this.name = name;this.age = age;
}const person = new Person('Tom', 18);// 构造函数的prototype就是实例对象的__proto__
console.log(Person.prototype === person.__proto__); // true// 实例对象的constructor指向构造函数
console.log(person.constructor === Person); // true// 实例对象的__proto__对象上的constructor指向的又是Person构造函数
console.log(person.__proto__.constructor === Person); // true// 实例对象的__proto__对象的__proto__指向的是Object构造函数的prototype
console.log(person.__proto__.__proto__ === Object.prototype); // true// 每一个构造函数也是一个对象,所以也都有__proto__属性,指向的是Function构造函数的prototype
console.log(Person.__proto__ === Function.prototype); // true// Function构造函数的prototype的constructor指向Function构造函数
console.log(Function.prototype.constructor === Function); // true// Function的prototype的__proto__指向Object的prototype
console.log(Function.prototype.__proto__ === Object.prototype); // true// 因为所有构造函数的__proto__都是指向Function的prototype,所以Function构造函数的prototype和__proto__是相等的
console.log(Function.__proto__ === Function.prototype); // true
1. 实例对象与构造函数的关系
console.log(Person.prototype === person.__proto__); // true
- 解析:
Person.prototype是构造函数Person的原型对象。person.__proto__是实例对象person的原型,指向Person.prototype。- 因此,
Person.prototype === person.__proto__返回true。
2. 实例对象的constructor属性
console.log(person.constructor === Person); // true
- 解析:
- 实例对象
person的constructor属性指向其构造函数Person。 - 因此,
person.constructor === Person返回true。
- 实例对象
3. 原型对象的constructor属性
console.log(person.__proto__.constructor === Person); // true
- 解析:
person.__proto__是Person.prototype,它有一个constructor属性,指向构造函数Person。- 因此,
person.__proto__.constructor === Person返回true。
4. 原型链向上查找
console.log(person.__proto__.__proto__ === Object.prototype); // true
- 解析:
person.__proto__是Person.prototype。Person.prototype.__proto__指向Object.prototype。- 因此,
person.__proto__.__proto__ === Object.prototype返回true。
5. 构造函数也是对象
console.log(Person.__proto__ === Function.prototype); // true
- 解析:
- 构造函数
Person本身是一个函数对象,所以它的__proto__属性指向Function.prototype。 - 因此,
Person.__proto__ === Function.prototype返回true。
- 构造函数
6. Function构造函数的关系
console.log(Function.prototype.constructor === Function); // true
console.log(Function.prototype.__proto__ === Object.prototype); // true
console.log(Function.__proto__ === Function.prototype); // true
- 解析:
Function.prototype是Function构造函数的原型对象。Function.prototype.constructor指向Function自身。Function.prototype.__proto__指向Object.prototype,因为函数也是对象。Function.__proto__指向Function.prototype,因为Function也是函数,是自己的构造函数。- 因此,上述三个
console.log均返回true。
三、原型链查找属性的过程
console.log(person.__proto__); // Person {}
console.log(person.__proto__.__proto__); // Object {}
console.log(person.__proto__.__proto__.__proto__); // null
- 解析:
person.__proto__是Person.prototype。person.__proto__.__proto__是Object.prototype。person.__proto__.__proto__.__proto__为null,表示原型链的顶端。
四、总结
1. 关于__proto__和prototype
-
__proto__:- 是每个对象都有的内置属性,指向其构造函数的原型对象。
- 用于实现对象的原型链,在查找属性时,如果对象自身没有,会沿着
__proto__向上查找。
-
prototype:- 是构造函数的属性,指向原型对象。
- 原型对象上定义的方法和属性会被构造函数的所有实例共享。
2. 关于构造函数和实例对象
-
实例对象的
__proto__:- 指向构造函数的
prototype属性。
- 指向构造函数的
-
实例对象的
constructor:- 通过
__proto__找到原型对象,原型对象的constructor指向构造函数。
- 通过
-
构造函数的
__proto__:- 因为构造函数本身是一个函数对象,所以它的
__proto__指向Function.prototype。
- 因为构造函数本身是一个函数对象,所以它的
3. 关于原型链的查找过程
- 当访问对象的属性时,JavaScript引擎会先查找对象自身的属性。
- 如果找不到,会沿着
__proto__属性指向的原型对象继续查找。 - 这个过程会一直持续,直到找到属性或到达原型链的顶端(
null)。
4. 关于Function和Object
-
Function构造函数:
- 是所有函数的构造函数,包括
Function自身。 Function.__proto__ === Function.prototype,因为Function是一个函数,其__proto__指向Function.prototype。
- 是所有函数的构造函数,包括
-
Object构造函数:
- 是所有对象的构造函数,包括
Function.prototype。 Function.prototype.__proto__ === Object.prototype。
- 是所有对象的构造函数,包括
五、深入思考
-
为什么
Function.__proto__ === Function.prototype?- 因为
Function是所有函数的构造函数,包括它自己。Function作为一个函数对象,其__proto__指向Function.prototype。
- 因为
-
为什么
Object.__proto__ === Function.prototype?Object是一个函数(构造函数),所以其__proto__指向Function.prototype。
-
为什么
Function.prototype.__proto__ === Object.prototype?Function.prototype是一个对象,因此其__proto__指向Object.prototype。
相关文章:
javascript中原型链(__proto__)与原型(prototype)
JavaScript中原型链(proto)与原型(prototype) 在JavaScript中,理解原型链(__proto__)和原型(prototype)对于深入掌握面向对象编程至关重要。本文将通过示例代码,详细解析__proto__和prototype之间的关系&a…...
基于多种机器学习的酒店客户流失预测模型的研究与实现
文章目录 有需要本项目的代码或文档以及全部资源,或者部署调试可以私信博主项目介绍实现过程 有需要本项目的代码或文档以及全部资源,或者部署调试可以私信博主 项目介绍 项目背景: 在当今竞争激烈的酒店行业中,预测和防止客户流…...
Unity实现自定义图集(三)
以下内容是根据Unity 2020.1.0f1版本进行编写的 1、实现编辑器模式下进游戏前Pack全部自定义图集 同Unity的图集一样,Unity的编辑器模式会在进游戏前把全部的SpriteAtlas都打一次图集,如图: 我们也实现这样的效果。 首先需要获取全部的图集路径。因为目前使用的是以.…...
【测开面试真题】
针对地图导航设计测试用例 文章目录 1. selenium 定位元素的方式有几种?2. 自动化测试能够取代人工测试吗?3. 什么是回归测试? 1. selenium 定位元素的方式有几种? 🐧①通过CSS选择器定位;🐧②…...
RelationGraph实现工单进度图——js技能提升
直接上图: 从上图中可以看到整个工单的进度是从【开始】指向【PCB判责】【完善客诉】【PCBA列表】,同时【完善客诉】又可以同时指向【PCB判责】【PCBA列表】,后续各自指向自己的进度。 直接上代码: 1.安装 1.1 Npm 方式 npm …...
针对脚本爬虫攻击的防御策略与实现
随着互联网的发展,网站和应用程序面临着越来越多的自动化攻击,其中包括使用脚本进行的大规模数据抓取,即所谓的“爬虫攻击”。这类攻击不仅影响网站性能,还可能导致敏感数据泄露。本文将探讨如何识别爬虫攻击,并提供一…...
JVM发展历程
JVM发展历程 Sun Classic VM 早在1996年Java1.0版本的时候,Sun公司发布了一款名为sun classic VM的Java虚拟机,它同时也是世界上第一款商用Java虚拟机,JDK1.4时完全被淘汰。这款虚拟机内部只提供解释器。现在还有及时编译器,因此…...
C语言 | Leetcode C语言题解之第470题用Rand7()实现Rand10()
题目: 题解: // The rand7() API is already defined for you. // int rand7(); // return a random integer in the range 1 to 7int rand10() {while(true) {int index (rand7() - 1) * 7 rand7(); if(index < 40) return index % 10 1; } }...
【JavaScript】拷贝对象的几种方式与对比
#工作中拷贝对象是常有的事,我们需要分清楚深浅拷贝,一般来说要做的都是深拷贝,不然会有关联影响# 解构赋值 es6新语法,简洁是简洁,但是需要注意深拷贝只针对第一层 使用方式:{...obj} let stu {name:…...
高防服务器为何有时难以防御CC攻击及其对策
高防服务器通常被用来抵御各种类型的DDoS攻击,包括CC(Challenge Collapsar)攻击。然而,在某些情况下,即使是配备了高级防护措施的高防服务器也可能难以完全防御CC攻击。本文将探讨导致这一现象的原因,并提供…...
性能测试工具locust —— Python脚本参数化!
1.1.登录用户参数化 在测试过程中,经常会涉及到需要用不同的用户登录操作,可以采用队列的方式,对登录的用户进行参数化。如果数据要保证不重复,则取完不再放回;如可以重复,则取出后再返回队列。 def lo…...
Java中的拦截器、过滤器及监听器
过滤器(Filter)监听器(Listener)拦截器(Interceptor)关注点web请求系统级别参数、对象Action(部分web请求)如何实现函数回调事件Java反射机制(动态代理)应用场…...
Nginx 和 Lua 设计黑白名单
使用 Nginx 和 Lua 设计黑白名单机制,借助 Redis 存储 在现代网络应用中,安全性是一个不可忽视的关键因素。应用程序需要能够有效地管理访问权限,以保护其资源不被恶意用户攻击。黑白名单机制是实现访问控制的一种有效方式。本文将详细介绍如…...
【部署篇】Redis-01介绍
一、Redis介绍 1、什么是Redis? Redis,英文全称是Remote Dictionary Server(远程字典服务),Redis是一个开源的、使用ANSI C语言编写的Key-Value存储系统,支持网络、可基于内存亦可持久化。 它提…...
R语言的Meta分析【全流程、不确定性分析】方法与Meta机器学习技术应用
Meta分析是针对某一科研问题,根据明确的搜索策略、选择筛选文献标准、采用严格的评价方法,对来源不同的研究成果进行收集、合并及定量统计分析的方法,最早出现于“循证医学”,现已广泛应用于农林生态,资源环境等方面。…...
【text2sql】ReFSQL检索生成框架
论文标题为《ReFSQL: A Retrieval-Augmentation Framework for Text-to-SQL Generation》,发表在 EMNLP 2023 上。ReFSQL框架通过结构增强检索器来获取与当前问题语义和模式结构相似的样本,然后通过对比学习机制来引导模型学习到这些样本的特定知识&…...
美国市场跨平台应用程序本地化流程的特点
为美国市场本地化移动应用程序是为了创造一种自然、直观、与多元化和精通技术的受众文化相关的体验。美国是世界上最大、最具竞争力的应用程序市场之一,用户期望高质量的性能以及在个人层面引起共鸣的内容。这个市场的本地化需要对美国语言、文化和行为有细致入微的…...
STM32 实现 TCP 服务器与多个设备通信
目录 一、引言 二、硬件准备 三、软件准备 四、LWIP 协议栈的配置与初始化 五、创建 TCP 服务器 1.创建 TCP 控制块 2.绑定端口 3. 进入监听状态 4.设置接收回调函数 六、处理多个客户端连接 七、数据处理与通信管理 八、错误处理与资源管理 九、总结 一、引…...
EdgeNAT: 高效边缘检测的 Transformer
EdgeNAT: Transformer for Efficient Edge Detection 介绍了一种名为EdgeNAT的基于Transformer的边缘检测方法。 1. 背景与动机 EdgeNAT预测结果示例。(a, b):来自BSDS500的数据集的输入图像。(c, d):对应的真实标签。(e, f):由EdgeNAT检测到的边缘。(e)显示了由于颜色变化…...
Github优质项目推荐 - 第六期
文章目录 Github优质项目推荐 - 第六期一、【WiFiAnalyzer】,3.4k stars - WiFi 网络分析工具二、【penpot】,33k stars - UI 设计与原型制作平台三、【Inpaint-Anything】,6.4k stars - 修复图像、视频和3D 场景中的任何内容四、【Malware-P…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
C++.OpenGL (14/64)多光源(Multiple Lights)
多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...
