【JS】JavaScript 中的原型与原型链

JavaScript 中的原型与原型链

      • 原型
        • 1 函数中 prototype 指向原型对象
        • 2 对象中 __proto__ 指向原型对象
        • 3 原型对象中 constructor 指向构造函数
        • 4 __proto__ 与 [[Prototype]] 的关系
        • 5 所有非空类型数据,都具有原型对象
        • 6 new运算符做了哪些事情
      • 原型链
        • 1 举个栗子
          • 1.1 直接创建一个对象
          • 1.2 数字、字符串、数组等类型数据, 下面以数字为例, 其他类型大同小异
          • 1.3 一个复杂的例子
        • 2 原型链的作用

原型

1 函数中 prototype 指向原型对象

当我们创建一个函数时,函数都会有一个默认属性 prototype

该属性指向一个对象, 该对象就被称之为 原型对象

function fun(){}
fun.prototype // 原型对象

在这里插入图片描述

2 对象中 proto 指向原型对象

当函数作为 普通函数 进行调用时,该属性不会有任何作用

当函数被作为 构造函数 进行调用 (使用 new 运算符调用) 时,构建出来的 实例对象 会有一个属性 __proto__ 指向 原型对象

function fun(name){this.name = name
}fun.prototype // 原型对象// 函数被作为构造函数进行调用
const obj = new fun('swim') // 实例对象.__proto__ 指向 构造函数.prototype
obj.__proto__ === fun.prototype // true

》》》2

3 原型对象中 constructor 指向构造函数

原型对象 默认会有一个特殊的属性 constructor, 该属性又指向了函数本身

function fun(name){this.name = name
}fun.prototype // 原型对象// 原型对象中 constructor 指向构造函数
fun.prototype.constructor === fun // true

在这里插入图片描述

4 proto 与 [[Prototype]] 的关系

如果将 实例对象 打印出来, 会发现对象中并不具有 __proto__ 属性,恰恰相反有个特殊的 [[Prototype]] 属性。

《《《《4

__proto__ 并不是 ECMAScript 语法规范的标准, 它只是大部分浏览器厂商实现或说是支持的一个属性, 通过该属性方便我们访问、修改原型对象

遵循 ECMAScript 标准, [[Prototype]] 才是正统, [[Prototype]] 无法被直接修改、引用

ECMAScript 6 开始, 可通过 Object.getPrototypeOf()Object.setPrototypeOf() 来访问、修改 原型对象

简单理解: __proto__[[Prototype]] 是同一个东西, __proto__ 是非标准的, [[Prototype]] 才是标准的, 但是它们都是指向 原型对象

那么问题来了, 我们访问的 __proto__ 在哪里呢? 实际上它是被添加在 Object.prototype 上, 然后通过 原型链(后面会详细展开说明) 我们就能够访问到该属性

5 所有非空类型数据,都具有原型对象

任何非空数据,本质上都是通过对应的构造函数构建出来的,所以他们都具有 __proto__ 属性,指向构造函数的原型对象。

如果需要判断某个值的原型对象,只需要确认该值是通过哪个构造函数构建的即可,只要确认了构造函数,那么该值的 __proto__ 必然指向该构造函数的原型对象 prototype

// 数字
const num = 1
// 数字是通过 Number 构建的, 那么其原型对象等于 Number.prototype
num.__proto__ === Number.prototype // true// 字符串
const str = 'str'
// 字符串是通过 String 构建的, 那么其原型对象等于 String.prototype
str.__proto__ === String.prototype // true// 布尔类型
const bool = false
// 布尔值是通过 Boolean 构建的, 那么其原型对象等于 Boolean.prototype
bool.__proto__ === Boolean.prototype // true// Symbol
const sym = Symbol('symbol')
// sym 是通过 Symbol 构建的, 那么其原型对象等于 Symbol.prototype
sym.__proto__ === Symbol.prototype // true// BigInt
const big = BigInt(1)
// big 是通过 BigInt 构建的, 那么其原型对象等于 BigInt.prototype
big.__proto__ === BigInt.prototype // true// 对象
const obj = { age: 18 }
// 对象是通过 Object 构建的, 那么其原型对象等于 Object.prototype
obj.__proto__ === Object.prototype // true// 函数
const fun = () => {}
// 函数是通过 Function 构建的, 那么其原型对象等于 Function.prototype
fun.__proto__ === Function.prototype // true// 数组
const arr = [1, 2, 3]
// 数组是通过 Array 构建的, 那么其原型对象等于 Array.prototype
arr.__proto__ === Array.prototype // true
6 new运算符做了哪些事情
  1. 创建一个新的空对象 A
  2. 往空对象挂载 构造函数 Com原型对象: 对象 A 创建 __proto__ 属性, 并将 构造函数prototype 属性赋值给 __proto__
  3. 执行 构造函数 Com: 改变 构造函数 this 指向, 指向空对象 A, 并执行 构造函数, 往空对象注入属性
  4. 判断 构造函数 是否返回一个对象?
  • 是: 如果 构造函数 也返回了一个对象 B, 则最终 new 出来的对象则为返回的对象 B
  • 否: 最终 new 出来的对象为最初创建的对象 A
因此当我们执行
var o = new Foo();实际上执行的是:
// 1. 创建一个新的空对象 A
let A = {};// 2. 往空对象挂载, 挂载构造函数 Com 的原型对象: obj.__proto__ === Com.prototype;
Object.setPrototypeOf(A, Com.prototype);// 3. 执行构造函数: 改变构造函数 this 指向, 指向对象 A, 往 A 注入属性
let B = Com.apply(A, args);// 4. 判断构造函数是否返回对象: 是则取返回值、否则取最初创建的对象 A
const newObj = B instanceof Object ? res : A;

原型链

原型链是一种对象之间的链接机制,它用于实现对象之间的继承和属性访问。

每个JavaScript对象都有一个原型(prototype),原型是一个对象或null。当你访问一个对象的属性时,如果该对象自身没有该属性,JavaScript 引擎会沿着原型链向上查找,直到找到具有该属性的对象或到达原型链的末尾(即null)。这样,对象可以继承其原型的属性和方法。

根据上文,所有非空数据,都可以通过 __proto__ 指向原型对象,如果原型对象非空,那么必然会有 __proto__ 指向自己的原型对象,如此一层一层往上追溯,依此类推,就形成了一整条链路,一直到某个原型对象为null,才能达到最后一个链路的最后环节,而原型对象之间这种链路关系被称之为原型链 (prototype chain)

1 举个栗子
1.1 直接创建一个对象
const obj = { age: 18 };从对象 obj 视角来看:
1. obj 本质上是通过 Object 构建出来的,那么 obj.__proto__ === Object.prototype
2. Object.prototype 的原型对象为 null,因此原型链到此结束

》》》图5

1.2 数字、字符串、数组等类型数据, 下面以数字为例, 其他类型大同小异
let num = 1;1. num 本质上是通过 Number 构建出来的,那么 num.__proto__ === Number.prototype
2. Number.prototype 本质上是一个对象,是通过 Object 构建出来的,那么 Number.prototype.__proto__ === Object.prototype
3. Object.prototype 的原型对象为 null,因此原型链到此结束num.__proto__ === Number.prototype // true
Number.prototype.__proto__ === Object.prototype // true
Object.prototype.__proto__  // null 原型链结束
1.3 一个复杂的例子
function Person(age) {this.age = age       
}
var person = new Person(100)从对象  person 视角来看:1. person 是通过 Person 构建出来的, 那么 person.__proto__ 等于 Person.prototype2. Person.prototype 是个对象, 是通过 Object 构建出来了, 那么Person.prototype.__proto__ 等于 Object.prototype3. Object.prototype 的 原型对象 为 null, 原型链 到此结束
2 原型链的作用
  • 查找属性: 当我们试图访问 对象属性 时, 它会先在 当前对象 上进行搜寻, 搜寻没有结果时会继续搜寻该对象的 原型对象, 以及该对象的 原型对象原型对象, 依次层层向上搜索, 直到找到一个名字匹配的属性或到达原型链的末尾
function Person(age) {this.age = age
}Person.prototype.name = 'klx'
Person.prototype.age = 18const person = new Person(28)person // 当前对象: { age: 28 }person.name // klx, 取自原型对象 Person.prototype
person.age // 28, 取自当前对象person.toString() // [object Object], 取自原型对象 Object.prototypeperson.address // undefined, 沿着原型链找不到 address 
  • 继承属性和方法:原型链允许对象继承其原型的属性和方法。当你访问一个对象的属性时,如果对象本身没有该属性,它会通过原型链访问原型对象的属性。这样可以实现属性的共享和代码的重用。

  • 创建对象关联:通过原型链,你可以将一个对象与另一个对象关联起来,形成一个对象链。这样,一个对象可以通过原型链访问到另一个对象的属性和方法。

  • 实现对象的多态性:在原型链中,可以通过在原型对象上定义相同名称的属性或方法,从而实现对象的多态性。当对象在原型链中找到具有相同名称的属性或方法时,会使用最近的那个

JavaScript中的原型链是基于原型继承的概念,它允许对象通过原型链接到其他对象,并继承其属性和方法。这种机制在JavaScript中是一种重要的特性,使得对象之间可以实现继承和共享,提供了灵活性和代码复用的机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/761342.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用有道bce-embedding-vase-v1模型构建知识向量库并进行相似度搜索

国产embedding 最开始使用LangChain结合通义千问API实现了基础的RAG(Retrieval-Augmented Generation)过程,当时认为embedding模型似乎是LangChain的一部分,然后又通过学习OpenAI的API发现,其实使用embedding模型不需要…

智能农业:农业技术与效益

文章目录 什么是智慧农业?智能农业的好处智能农业技术物联网智能农业解决方案智能农业软件和移动应用程序智能农业的挑战作物监测卫星智能农业解决方案使用卫星数据数据测量历史数据和预测在便携式设备上使用应用程序 智能农业的未来参考 现代技术的发展影响着人类活…

走进jvm之垃圾回收器篇

这里我想首先说明一下,虽然我们经常会拿垃圾回收器来做比较,虽然想挑选一个最好的收集器出来,但是目前也没有说哪一款收集器是完美的,更不存在万能的收集器,我们也只是对收集器选择最适合场景的一个收集器。 那么作者将…

深入解析权限之钥RBAC模型!

在2B系统中设计中,角色基于访问控制(RBAC,Role-Based Access Control)是最常见的权限管理模型之一。它将权限分配给角色而非个别用户,简化了权限管理的过程。接下来我们一起了解下几种常见的RBAC模型。 1. 标准 RBAC&…

母亲的奶牛(蓝桥杯,acwing每日一题)

题目描述: 农夫约翰有三个容量分别为 A,B,C升的挤奶桶。 最开始桶 A 和桶 B 都是空的,而桶 C 里装满了牛奶。 有时,约翰会将牛奶从一个桶倒到另一个桶中,直到被倒入牛奶的桶满了或者倒出牛奶的桶空了为止。 这一过程中间不能有…

每日学习笔记:C++ STL 的无序容器(unordered_set、unordered_map)

定义 特性 能够快速查找元素 操作函数 负载系数 元素个数 / bucket个数 提供哈希函数 提供等价准则 方法一:重写元素的操作符 方法二:自定义函数对象 提供自定义哈希函数和等价准则例子 例一:传入函数对象 例二:传入lambda 检…

蓝桥杯2023省赛:矩阵总面积|模拟、数学(几何)

题目链接: 0矩形总面积 - 蓝桥云课 (lanqiao.cn) 说明: 参考文章:矩形总面积计算器:计算两个矩形的总面积,包括重叠区域_矩形r1的左下角坐标为x1, yl 、宽度为w1、高度为h1, 矩形r2的左下角坐标为x2,y2、宽-CSDN博客…

移卡 2023 年支付GPV超 2.88 万亿 龙头地位稳固

3月21日,中国领先的基于支付的科技平台——移卡有限公司(以下简称“移卡”或“公司”,股份代号:09923.HK)发布2023年年度业绩报告。与上年同期相比,移卡2023年收入同比增长15.6%,至人民币39.51亿…

Java代码基础算法练习-求一个三位数的各位平方之和-2024.03.21

任务描述&#xff1a; 输入一个正整数n&#xff08;取值范围&#xff1a;100<n<1000&#xff09;&#xff0c;然后输出每位数字的平方和。 任务要求&#xff1a; 代码示例&#xff1a; package march0317_0331;import java.util.Scanner;public class m240321 {public …

YOLOV5 改进:替换backbone为Swin Transformer

1、前言 本文会将YOLOV5 backbone更换成Swin Transformer 具体为什么这样实现参考上文:YOLOV5 改进:替换backbone(MobileNet为例)-CSDN博客 这里只贴加入的代码 训练结果如下: 2、common文件更改 在common文件中加入下面代码: 这里是swin transformer的实现,参考:…

如何申请免费通配符SSL证书

步骤1&#xff1a;了解免费通配符证书的选项 首先&#xff0c;您需要了解哪些机构或项目提供免费的通配符证书。目前绝大部分CA机构只提供免费的单域名证书&#xff0c;只有少数服务商提供商可以提供免费的通配符证书&#xff0c;比如JoySSL。 免费通配符证书申请地址https://…

GPT2从放弃到入门(二)

引言 本文介绍如何利用GPT2从零训练一个多轮对话聊天机器人&#xff0c;按照本文的思路可以轻松地训练自己的数据。 数据处理 ⚠️ 这是本文的核心部分&#xff0c;其他的内容甚至可以不用看。 本小节阐述多轮对话数据的处理。 数据来自网上的一份开源数据&#xff1a;htt…

Java特性之设计模式【装饰器模式】

一、装饰器模式 概述 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其结构。这种类型的设计模式属于结构型模式&#xff0c;它是作为现有的类的一个包装 装饰器模式通过将对象包装在装饰器类中&#xff0c;以…

C语言牛客网刷题

1.最大公约数和最小公倍数的组合问题 &#xff08;1&#xff09;在调试的过程中涉及到很大的数据&#xff0c;我们我们在定义变量的时候定义为long long类型 &#xff08;2&#xff09;这个里面我们自定义了max2用来求最大公约数&#xff0c;min2用来求最小公倍数 &#xff0…

MYSQL报 - Lock wait timeout exceeded; try restarting transaction

前言 今天在使用数据库编辑数据时&#xff0c;页面突然卡主&#xff0c;退出程序后重新编辑&#xff0c;发现报错&#xff0c;1205 - Lock wait timeout exceeded&#xff1b; try restarting transaction&#xff08;如下图&#xff09;&#xff0c;正巧在和同事开会&#xf…

大屏页面 电子数字 制作

字体包下载地址 链接: https://pan.baidu.com/s/1pjslpT5QQi7-oALDM-uX8g 提取码: zxcv 效果展示 使用前使用后 使用方式 1.解压后将文件夹放入public 2.在公用样式中加入 font-face {font-family: mFont;src: url(../../public/DS-Digital/DS-DIGI-1.ttf); } 3. 在项目…

技术总结: 基于http3的动态网页图片爬虫设计

目录 写在前面第一步: 打开网页第二步: 学会模拟浏览器发送请求第三步: 分析网页结果, 找到爬取内容第四步: 处理动态网页 所有程序 写在前面 作为一名算法工程师, 收集处理数据的能力也是比较重要的. 能够充分利用好互联网的数据资源, 加上优秀的算法能力, 就如虎添翼. 这次就…

关于在CentOS中卸载MySQL

想要卸载MySQL当然要知道自己的MySQL是用那种方法来安装的了&#xff0c;一般来说MySQL的安装方法在市面上有三种 编译安装、YUM安装、RPM安装&#xff0c;下面会介绍到后两种安装的卸载方法 首先查看是否安装MySQL&#xff0c;一般可以看到版本信息就证明安装了 mysql -V 卸载…

【DL经典回顾】激活函数大汇总(四十二)(CosReLU附代码和详细公式)

激活函数大汇总(四十二)(CosReLU附代码和详细公式) 更多激活函数见激活函数大汇总列表 一、引言 欢迎来到我们深入探索神经网络核心组成部分——激活函数的系列博客。在人工智能的世界里,激活函数扮演着不可或缺的角色,它们决定着神经元的输出,并且影响着网络的学习能…

【热门话题】深入浅出:npm常用命令详解与实践

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 标题&#xff1a;深入浅出&#xff1a;npm常用命令详解与实践引言一、npm基本概…