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…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
jmeter聚合报告中参数详解
sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample(样本数) 表示测试中发送的请求数量,即测试执行了多少次请求。 单位,以个或者次数表示。 示例:…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...

网页端 js 读取发票里的二维码信息(图片和PDF格式)
起因 为了实现在报销流程中,发票不能重用的限制,发票上传后,希望能读出发票号,并记录发票号已用,下次不再可用于报销。 基于上面的需求,研究了OCR 的方式和读PDF的方式,实际是可行的ÿ…...
嵌入式面试常问问题
以下内容面向嵌入式/系统方向的初学者与面试备考者,全面梳理了以下几大板块,并在每个板块末尾列出常见的面试问答思路,帮助你既能夯实基础,又能应对面试挑战。 一、TCP/IP 协议 1.1 TCP/IP 五层模型概述 链路层(Link Layer) 包括网卡驱动、以太网、Wi‑Fi、PPP 等。负责…...