JavaScript---原型和原型链
目录
一、引用类型皆为对象
二、原型和原型链是什么
三、__proto__与prototype
总结
四、原型链顶层
五、constructor
六、函数对象的原型链
一、引用类型皆为对象
原型和原型链都是来源于对象而服务于对象:
- JavaScript中一切引用类型都是对象,对象就是属性的集合
- Array、Function、Object、Date、RegExp都是引用类型
- 数组是对象、函数是对象、正则是对象、对象还是对象
const arr = []
const fn = function() {}
const obj = {}console.log(typeof arr) // "object"
console.log(fn instanceof Object) // true
console.log(typeof obj) // "object"
二、原型和原型链是什么
每一个对象从被创建开始就和另一个对象关联,从另一个对象上继承其属性,这个“另一个对象”就是“原型”
当访问一个对象的属性时,先在对象的本身查找,找不到就去对象的原型上找,如果还找不到,就去对象的原型的原型上去找,如此重复,直到找到为止,或者查找到最顶层的原型对象中也没有找到,就结束查找,返回undefined
而在对象的原型上,依次查找时,所遍历的所有原型,叫作“原型链”
const obj = {}
obj.sayHello = () => {console.log('Hello')}
console.log(obj.hasOwnProperty('sayHello')) // true
- 上面代码中,我们访问obj.hasOwnProperty()时,发现该对象并没有这个方法,但是我们仍然可以使用,这是因为在obj对象的原型上,存在该方法,所以我们可以调用
- 到现在,我们可以理解数组可以使用push、slice等方法,函数可以使用call、bind方法了,因为在它们的原型链上找到了对应的方法
三、__proto__与prototype
每个对象都有原型,我们怎么获取到一个对象的原型呢?可以使用对象的“__proto__”属性,指向对象的原型
- 所有引用类型都有__proto__属性

- __proto__属性在ES6中不推荐被使用,现在更推荐使用Obejct.getPrototypeOf(),该方法也可以获取到对象的属性
console.log(Object.getPrototypeOf(obj) === obj.__proto__) // true
构造函数是为了创建特定类型的对象,那如果我想让“Person”这个构造函数创建的对象都共享一个方法,不能像下面这样:
错误示范:
function Person(name){this.name = name;
}
// 调用构造函数Person创建一个新对象PersonA
const personA = new Person();
// 给PersonA的原型添加一个方法,以供之后Person创建的对象共享
personA.__proto__.sayHello = function(){console.log(`Hello, my name is ${this.name}`);
}
// 创建一个新的Person对象PersonB
const personB = new Person('Bob');
// 调用PersonB的sayHello方法
personB.sayHello(); // Hello, my name is Bob
- 当我们不想修改构造函数创建的对象,并且还不想修改构造函数时,如果先通过构造函数创建一个对象,再通过对象的原型修改,这样确实可以,但实在太过啰嗦
为此,我们可以通过“prototype”来直接修改原型,每个函数多拥有prototype属性,指向使用new操作符和该函数创建的对象的实例的原型对象
console.log(personA.__proto__ === Person.prototype); // true
console.log(personB.__proto__ === Person.prototype); // true
正确示范:
function Person(name){this.name = name;
}
Person.prototype.sayHello = function(){console.log(`Hello, my name is ${this.name}`);
}
const personA = new Person('Bob');
personA.sayHello(); // Hello, my name is Bob
总结
- 对象有__proto__属性(Object.create(null)除外),函数有__proto__属性,数组也有__proto__属性,只要是引用类型,就有__proto__属性,指向其原型
- 只有函数有prototype属性,指向new操作符加调用该函数创建的对象实例的原型对象
四、原型链顶层
原型链之所以叫原型链,不叫原型环,说明它是有始有终的,那么原型链的顶层是什么呢?
personA对象的原型对象,很简单:
console.log(personA.__proto__ === Person.prototype);
接着往上找,Person.prototype也是一个普通对象,可以理解为Object构造函数创建的,所以得出下面结论:
console.log(Person.prototype.__proto__ === Object.prototype); // true
console.log(Person.prototype.__proto__)

- 上图红框内的__proto__就是Person.prototype.__proto__,也就是下图:

Object.protype也是一个对象,那么它的原型呢?是空值null
Object.prototype.__proto__ === null
五、constructor
构造函数都有一个prototype属性,指向使用这个构造函数创建的对象实例的原型对象
这个原型对象中默认有一个constructor属性,指回该构造函数
Person.prototype.constructor === Person // true

六、函数对象的原型链
函数也是对象,故函数也有__proto__属性,这里比较容易混淆
因为函数既有prototype也有__proto__,很容易搞晕
我们只需要记住:
- 函数的prototype使用的前提是:“函数被作为构造函数使用,此时prototype指向构造函数创建的对象实例的__proto__原型对象”
- 函数的__proto__指的是:“函数被当做一个普通对象使用,此时它的__proto__指向Function.prototype,因为Function是所有函数的构造函数”
- 一个特例,Fyunction.__prototype === Function.prototype,记住就好
console.log(Person.__proto__ === Function.prototype) // true
console.log(Person.__proto__.constructor === Function) // true
console.log(Person.__proto__.__proto__ === Object.prototype) // true
有点绕,但是理解这三个代码,相信__proto__和prototype你永远不会弄混了
相关文章:
JavaScript---原型和原型链
目录 一、引用类型皆为对象 二、原型和原型链是什么 三、__proto__与prototype 总结 四、原型链顶层 五、constructor 六、函数对象的原型链 一、引用类型皆为对象 原型和原型链都是来源于对象而服务于对象: JavaScript中一切引用类型都是对象,…...
离散数学问题集--问题5.9
问题 5.9 综合了计算机组成原理、数字逻辑和离散数学中的关键概念,旨在帮助学生理解二进制算术运算的硬件实现、逻辑门与算术运算的关系,以及如何使用数学方法来验证数字系统的正确性。它强调了从规范到实现再到验证的完整过程。 思想 函数抽象…...
手游防DDoS攻击SDK接入
在手游中集成防DDoS攻击SDK是抵御流量型和应用层攻击的核心手段之一。以下从SDK选型、接入流程、防护策略优化三个维度提供完整指南,并附关键代码示例: 一、SDK选型与核心能力对比 服务商优势劣势适用场景…...
Java—HTML:CSS选择器
今天我要介绍的知识点内容是Java HTML中的CSS选择器; CSS选择器用于定位HTML元素并为其添加样式。它允许我们控制网页的颜色、字体、布局和其他视觉元素。通过分离内容与样式。 下面我将介绍CSS中选择器的使用,并作举例说明; 选择器基本语…...
如何将/dev/ubuntu-vg/lv-data的空间扩展到/dev/ubuntu-vg/ubuntu-lv的空间上
要将 /dev/ubuntu-vg/lv-data 的空间扩展到 /dev/ubuntu-vg/ubuntu-lv 上,实际上是将 lv-data 的空间释放出来,并将其分配给 ubuntu-lv。以下是详细的步骤和操作说明: 已知信息 你有两个逻辑卷: /dev/ubuntu-vg/lv-data/dev/ubun…...
SSM阶段性总结
0 Pojo类 前端给后端:DTO 后端给前端:VO 数据库:PO/VO 业务处理逻辑:BO 统称pojo 1 代理模式 实现静态代理: 1定义接口2实现类3写一个静态代理类4这样在调用时就可以使用这个静态代理类来实现某些功能 实现动态代…...
Qt 5.14.2入门(一)写个Hello Qt!程序
目录 参考链接:一、新建项目二、直接运行三、修改代码增加窗口内容1、Qt 显示一个 QLabel 标签控件窗口2、添加按键 参考链接: Qt5教程(一):Hello World 程序 Qt 编程指南 一、新建项目 1、新建一个项目(…...
Jmeter分布式测试启动
代理客户端配置 打开jmeter.properties文件,取消注释并设置端口(如server_port1099), 并添加server.rmi.ssl.disabletrue禁用SSL加密。 (Linux系统)修改jmeter-server文件中的RMI_HOST_DEF为代理机实际IP。…...
redis itheima
缓存问题 核心是如何避免大量请求到达数据库 缓存穿透 既不存在于 redis,也不存在于 mysql 的key,被重复请求 public Result queryById(Long id) {String key CACHE_SHOP_KEYid;// 1. redis & mysqlString shopJson stringRedisTemplate.opsFo…...
mysql 执行计划中eq_ref是什么意思?
在 MySQL 的执行计划中,eq_ref 是一种连接类型(type),表示查询优化器在使用**主键(PRIMARY KEY)或唯一索引(UNIQUE INDEX)**进行等值匹配()时,对表…...
QT 调用动态链接库
引入QT提供的动态加载库的类 #include <QLibrary>定义函数指针类型 typedef void (*GetResFunction)(uint8_t*, uint8_t*, int);定义函数指针的主要目的是为了解析和调用动态链接库中的函数。如果你不定义函数指针,就无法直接调用动态链接库中的函数 加载动…...
100天精通Python(爬虫篇)——第122天:基于selenium接管已启动的浏览器(反反爬策略)
文章目录 1、问题描述2、问题推测3、解决方法3.1 selenium自动启动浏览器3.2 selenium接管已启动的浏览器3.3 区别总结 4、代码实战4.1 手动方法(手动打开浏览器输入账号密码)4.2 自动方法(.bat文件启动的浏览器) 1、问题描述 使用…...
MPP 架构解析:原理、核心优势与对比指南
一、引言:大数据时代的数据处理挑战 全球数据量正以指数级增长。据 Statista 统计,2010 年全球数据量仅 2ZB,2025 年预计达 175ZB。企业面临的核心挑战已从“如何存储数据”转向“如何快速分析数据”。传统架构在处理海量数据时暴露明显瓶颈…...
GitHub 趋势日报 (2025年04月06日)
GitHub 趋势日报 (2025年04月06日) 本日报由 TrendForge 系统生成 https://trendforge.devlive.org/ 📈 今日整体趋势 Top 10 排名项目名称项目描述今日获星语言1microsoft/markitdownPython tool for converting files and office documents to Markdown.⭐ 548Py…...
Python设计模式-工厂模式
一、模式定义与核心思想 工厂模式(Factory Pattern)属于创建型设计模式,其核心思想是通过一个"工厂类"来创建对象,而不是直接调用类的构造函数。这种模式将对象的实例化过程封装起来,使系统在实例化对象时能…...
SAP-ABAP:SAP的Open SQL和Native SQL详细对比
在SAP ABAP开发中,Open SQL和Native SQL是两种操作数据库的方式,它们的核心区别在于可移植性、功能范围及底层实现机制。以下是详细对比: 1. Open SQL:深入解析 1.1 核心特性 数据库抽象层 Open SQL 由 SAP 内核的 Database Interface (DBI) 转换为目标数据库的 SQL(如 …...
蓝桥杯 拼数(字符串大小比较)
题目描述 设有 n 个正整数 a1…an,将它们联接成一排,相邻数字首尾相接,组成一个最大的整数。 输入格式 第一行有一个整数,表示数字个数 n。 第二行有 n 个整数,表示给出的 n 个整数 ai。 输出格式 一个正整…...
Server-Sent Events一种允许服务器向客户端发送实时更新的 Web API
Server-Sent Events(SSE)是一种允许服务器向客户端发送实时更新的 Web API。它基于 HTTP 协议,提供了一种单向的、服务器到客户端的通信机制,客户端可以通过监听服务器发送的事件来接收实时数据。下面从原理、使用场景、代码示例等…...
彻底解决VS2008编译错误:fatal error C1083 无法打开包括文件“stdint.h“
彻底解决VS2008编译错误:fatal error C1083 无法打开包括文件"stdint.h" 一、错误现象与本质原因 当在Visual Studio 2008中编译包含C99标准整数类型(如int8_t、uint32_t)的代码时,常出现以下编译错误: f…...
react从零开始的基础课
全文约5万字。 1.hello,.. // App.jsx import { useState } from react import reactLogo from ./assets/react.svg import viteLogo from /vite.svg import ./App.cssfunction App() {const [count, setCount] useState(0)return (<><Greeting name"world&qu…...
算法题型讲解
一.双指针 主要分为俩种类型: 1.左右指针:双指针指向开头,以一定标准移动或交换,对区域进行划分,或找到特殊点的位置 (如:快慢指针判断有无环,移动零) 2.对撞指针&am…...
操作主机的管理
1.在AD林范围内,有哪几个操作主机角色 架构主机(Schema Master) 功能:负责整个AD林中所有对象和属性的定义,是唯一可以更新目录架构的DC。架构更新会从架构主机复制到目录林中的所有其他域控制器。 作用范围…...
Redis和数据库一致性问题
操作模拟 1、先更新数据库还是先更新缓存? 1.1先更新缓存,再更新数据库 按并发的角度来说,有两个线程A、B,操作同一个数据,线程A先更新缓存为1,在线程A更新数据库之前,这时候线程B进来&#…...
第R8周:RNN实现阿尔茨海默病诊断(pytorch)
>- **🍨 本文为[🔗365天深度学习训练营]中的学习记录博客** >- **🍖 原作者:[K同学啊]** 本人往期文章可查阅: 深度学习总结 一、准备工作 🏡 我的环境: 语言环境:Python3.1…...
《穿透表象,洞察分布式软总线“无形”之奥秘》
分布式系统已成为众多领域的关键支撑技术,而分布式软总线作为实现设备高效互联的核心技术,正逐渐走入大众视野。它常被描述为一条“无形”的总线,这一独特属性不仅是理解其技术内涵的关键,更是把握其在未来智能世界中重要作用的切…...
C++基础精讲-02
文章目录 1.C/C申请、释放堆空间的方式对比1.1C语言申请、释放堆空间1.2C申请、释放堆空间1.2.1 new表达式申请数组空间 1.3回收空间时的注意事项1.4malloc/free 和 new/delete 的区别 2.引用2.1 引用的概念2.2 引用的本质2.3 引用与指针的联系与区别2.4 引用的使用场景2.4.1 引…...
【网络安全】Linux 命令大全
未经许可,不得转载。 文章目录 前言正文文件管理文档编辑文件传输磁盘管理磁盘维护网络通讯系统管理系统设置备份压缩设备管理其它命令前言 在网络安全工作中,熟练掌握 Linux 系统中的常用命令对于日常运维、日志分析和安全排查等任务至关重要。 以下是常用命令的整理汇总,…...
双相机结合halcon的条码检测
以下是针对提供的C#代码的详细注释和解释,结合Halcon库的功能和代码结构进行说明: --- ### **代码整体结构** 该代码是一个基于Halcon库的条码扫描类GeneralBarcodeScan,支持单台或双台相机的条码检测,并通过回调接口返回结果。…...
C++学习之ORACLE①
目录 1.ORACLE数据库简介 2..ORACLE数据库安装 3..ORACLE体系结构 4..ORACLE基本概念 5..ORACLE基本元素 6..ORACLE数据库启动和关闭 7.SQLPLUS登录ORACLE数据库相关操作 8.SQLPLUS的基本操作 9.oracle中上课使用的方案 10.SQL语言分类 11.SQL中的select语句语法和注…...
setInterval问题以及前端如何实现精确的倒计时
一、为什么setInterval不能实现 原因有两:1、js是单线程,基于事件循环执行其他任务(这里建议读者可以多去了解一下浏览器线程与事件循环相关知识) 2、setinterval是每隔delay时间,把逻辑放到任务队列中,而…...
