快速理解JS中的原型和原型链

快速理解JS中的原型和原型链

在我们学习JS的过程中,我们总会接触到一些词:“原型”,“原型链”。那么今天我就来带大家来学习学习原型和原型链的知识吧!

在开始之前,我们明确一下我们接下来想要学习的目标:

  • 什么是原型?
  • 什么是原型链?
  • 原型和原型链之间有什么关系?
  • 原型和原型链有什么作用?

原型

什么是原型呢?每个构造函数创建的对象都会在创建的时候自带(创建)一个 prototype 属性,这个属性是一个对象,这个对象就是我们要说的原型。是不是有点绕?来看下面这个例子:

function Person(){}										Person.prototype.name="zhangsan"
Person.prototype.sayName=function(){console.log("lisi")
}const p1 = new Person()
console.log(p1.name)//zhangsan
console.log(p1.__proto__)// {name:"zhnagsan"}
console.log(p1.constructor)// [Function: Person]
console.log(Person.prototype===p1.__proto__)// true
console.log(Person.prototype.contructor===Person)// true

从这个例子可以看出,p1 是构造函数Peron()的实例对象,而实例对象通过__proto__Personprototype 属性连接起来了。看到这里,你是不是还是很疑惑,它们两个怎么就连接起来了?这就需要了解一下下面的知识点了:

  • 构造函数通常会有两个原型对象,一个是隐式原型__proto__,一个是显示原型prototype。而隐式原型是每一个对象都会拥有的。
  • 原型的一个作用大致可以理解成作为实例对象和构造函数之间的桥梁,但是请注意:实例对象与构造函数原型有直接联系,但是实例对象和构造函数之间没有直接联系!
  • 使用原型对象的还有一个好处是,在它上面定义的属性和方法可以被对象实例共享。也就是Person.prototype上面的属性和方法都会共享给实例对象,而且一个原型对象可以有多个实例的指向。
  • Person.prototype是 Person 构造函数的原型
  • p1.__proto__是实例对象 p1 的隐式原型,通过隐式原型可以访问对象的原型
  • 如上所述,构造函数有一个prototype属性引用其原型对象,而这个原型对象也有一个constructor属性,引用这个构造函数。也就是两者相互循环引用。
    在这里插入图片描述

原型链

看完了上面内容,相信你已经对原型已经有了大概的了解,接下来我们进阶了解一下原型链吧。看完上面的内容其实就很好理解原型链了,我们知道在使用实例对象的时候可以使用一些方法,像 toString、valueOf等,但是我们并没有在实例对象中定义这些方法,那这些方法是那里来的呢,实际上这些方法都是实际对象通过原型链到Object那里“拿”的。当我们调用一个对象中没有定义的方法时,JS 引擎会沿着原型链向上查找,直到找到该方法或达到原型链的顶端。(原型链也就是上图中右边一直向上“链条")。
在这里插入图片描述
这时候就会有人问:那么 JS 引擎是怎么利用原型链搜索的呢?请看下面的例子:

function Peronson(){}
Person.prototype.name="zhangsan"const p1=new Person();
console.log(p1.name)// zhangsan
p1.name="lisi"
console.log(p1.name)// lisi

JS 引擎在第一次打印的时候会问 p1 实例有 name 属性吗,答案是没有。然后继续搜索并问:p1 的原型有 name 属性吗?答案是有的,于是就返回了保存在原型上的这个 name 属性。第二次打印的时候 JS 引擎会问 p1 实例有 name 属性吗,答案是有的,于是就返回了保存在实例上的这个 name 属性。

实际上,在第二次打印的时候,p1原型上的 name 属性已经被 p1 实例的 name 属性给遮蔽了,也就是说虽然不会修改它,但会屏蔽它对原型上的同名属性。即时在实例上把这个属性设置为 null,也不会恢复它和原型的联系。不过使用 delete 操作符可以完全删除实例上的这个属性,从而让标识符解析过程能够继续搜索原型对象。

function Peronson(){}
Person.prototype.name="zhangsan"const p1=new Person();
console.log(p1.name)// zhangsan
p1.name="lisi"
console.log(p1.name)// lisi
delete p1.name
console.log(p1.name)// zhangsan

hasOwnProperty方法用于确定某个属性是在实例上还是在原型对象上,会在属性存在与掉用它的对象实例上时返回 true

function Person(){}const p1=new Person();
console.log(p1.name)// zhangsan,来自原型
console.log(p1.hasOwnProperty("name"))// false
p1.name="lisi"
console.log(p1.name)// lisi,来自实例
console.log(p1.hasOwnProperty("name"))// true

有人会说,这仅仅只是一个实例和其构造函数的原型链,那更复杂应该是什么样的呢?大家不妨想想,如果原型是另一个类型的示例呢?那就意味着这个原型本身有一个内部指针指向另一个原型,相应地另一个原型也有一个指针指向另一个构造函数。这样就在实例和原型之间构造了一条原型链。

function SuperType() {this.property = true
}SuperType.prototype.getSuperValue = function () {return this.property
}function SubType() {this.subproperty = false
}SubType.prototype = new SuperType()SubType.prototype.getSubValue = function () {return this.subproperty
}let instance = new SubType()
console.log(instance.getSuperValue()) // true

这里SuperType的实例作为SubType原型的一个属性,那么SuperType原型上的方法都会被SubType的示例所继承,这个例子就能够很好的体现出什么原型链和原型链的作用。

到这里,我们已经对原型有了大概的认识,那接下来我们来尝试一下回答上开头提出的几个问题:

  • 什么是原型?
    JS 中所有的对象都有一个内置属性,称为它的 prototype(原型) - MDN

  • 什么是原型链?
    原型本身是一个对象,故原型对象也会有它自己的原型,逐渐构成了原型链。原型链终止于拥有 null 作为其原型的对象上(内置一个_proto_ 属性并指向其构造函数的prototype的对象就是原型) - MDN。

  • 原型和原型链之间有什么关系?
    原型链由一个或多个原型链的指向形成的

  • 原型和原型链有什么作用?
    JS的属性共享和继承机制(当然,属性共享在某些场景下也是它的问题所在)

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

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

相关文章

新型[datahelper@onionmail.org].datah 勒索病毒来袭:如何筑起安全防线?

在数字化时代,网络安全问题日益凸显,其中勒索病毒成为了一种非常严重的威胁。[datahelperonionmail.org].datah勒索病毒就是其中的佼佼者,它以其复杂的加密手段和恶劣的勒索行为,给用户带来了巨大的损失。本文将从病毒的运行机制、…

JS中的JSON(秒懂如何操作JSON)

目录 一、JSON介绍 1.概念 2.主要特点 3.优点 4.使用JSON的原因 使用 XML 使用 JSON 二、JSON语法 三、JSON使用 1.JSON的序列化 2.解析(parse) JSON 3.序列化(Stringify)JSON 四、JSON实例 1.用户信息 2.本地存储 五、JSON应用…

C++计算器类成员的实现

请编程完成如下任务: 根据类的定义,完成该类成员函数的实现。 编写main()函数,分别以默认值和输入的值num创建对象c1和c2,调用成员函数对c1的数据成员增加1,c2的数据成员减少1,然后分别输出c1和c2的数据成员。 函数接…

mapbox 工作问题暂时记录

mapbox 工作问题暂时记录 mapbox样式修改1.2.3.4. mapbox样式修改 1. mapbox直接用class名无法修改样式, 可以添加 :deep 来修改样式 2. map.value.getStyle().layers这行代码可以获取页面中所有图层,可以判断图层id来做相应操作 3. map.value.setLayoutProperty(layer.id…

ModuleNotFoundError: No module named ‘mlxtend‘

from mlxtend.plotting import plot_decision_regions 报错信息: ModuleNotFoundError: No module named mlxtend Jupyter和Spyder报错原因:因为anaconda下没有这个模块,需要安装mlxtend 解决方案: 1.打开anaconda(或终端) 2. 点击路径点…

Python爬虫之Scrapy框架基础

Scrapy爬虫框架介绍 文档 英文文档中文文档 什么是scrapy 基于twisted搭建的异步爬虫框架. scrapy爬虫框架根据组件化设计理念和丰富的中间件, 使其成为了一个兼具高性能和高扩展的框架 scrapy提供的主要功能 具有优先级功能的调度器去重功能失败后的重试机制并发限制ip使用次…

完全可定制的富文本编辑器:逻辑清晰,插件赋能 | 开源日报 No.218

ianstormtaylor/slate Stars: 28.8k License: MIT slate 是一个完全可定制的框架,用于构建富文本编辑器。 可以构建类似 Medium、Dropbox Paper 或 Google Docs 的富文本编辑器通过一系列插件实现所有逻辑,避免代码复杂度受到 Draft.js、Prosemirror 和…

1.grpc-教程(golang版)

目录 一、介绍 二、环境准备 三、Golang中使用grpc 1.编写protobuf文件 2.服务端 3.客户端 四、proto文件详解 1.proto语法 2.数据类型 基本数据类型 数组类型 map类型 嵌套类型 编写风格 3.多服务 4.多个proto文件 五、流式传输 1.普通rpc 2.服务器流式 …

基于SVM的时间序列预测模型matlab代码

整理了基于SVM的时间序列预测模型matlab代码, 包含数据集。采用了四个评价指标R2、MAE、MBE、MAPE对模型的进行评价。SVM模型在数据集上表现非常好。 Mean squared error 0.000180613 (regression) Squared correlation coefficient 0.995639 (regression) Mea…

【进阶六】Python实现SDVRPTW常见求解算法——自适应大邻域算法(ALNS)

基于python语言,采用经典自适应大邻域算法(ALNS)对 带硬时间窗的需求拆分车辆路径规划问题(SDVRPTW) 进行求解。 目录 往期优质资源1. 适用场景2. 代码调整2.1 需求拆分2.2 需求拆分后的服务时长取值问题 3. 求解结果4…

QT4和QT5区别

Qt4.8.7是Qt4的终结版本,是Qt4系列版本中最稳定最经典的。 1、 在pro文件中添加QT widgets模块,如果添加这个模块后,带有”QtGui/”的类一部分类型就不需要这个前缀了,可以直接用用本身的类名。 2、 将带有QTGui的类替换为QTWi…

信息收集-app,小程序,公众号,邮箱篇

*声明:*请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。合法渗透,本文章内容纯属虚构,如遇…

【linux】sudo 与 su/su -之间的区别

一、区别 二、其他 大概是因为使用 su 命令或直接以 root 用户身份登录有风险,所以,一些 Linux 发行版(如 Ubuntu)默认禁用 root 用户帐户。鼓励用户在需要 root 权限时使用 sudo 命令。 然而,您还是可以成功执行 su…

反射+配置文件+抽象工厂模式

反射配置文件抽象工厂模式 文章目录 反射配置文件抽象工厂模式优化方案 优化方案 为了进一步优化代码,我们可以将产品类型与类名的映射关系存储在配置文件中,使得系统更易于管理和扩展。以下是在上述代码基础上添加配置文件的优化示例: 1.配…

快速熟悉torchdiffeq用法,从数理逻辑到完整案例【第二、三部分】

本系列文章板块规划 提示:以下内容仅为个人学习感悟,无法保证完全的正确和权威,大家酌情食用谢谢。 第一部分 torchdiffeq背后的数理逻辑 第二部分 torchdiffeq的基本用法 第三部分 trochdiffeq的升级用法 第四部分 torchdifffeq的案例和代码…

一文解决集合框架源码(一)

文章目录 1. 集合框架结构2. Iterable接口3. Conllection接口4. List接口5. Set接口6. Queue接口7. Deque接口8. ArrayList类9. Vector类10. Stack类11. LinkedList类12. HashSet类13. LinkedHashSet类14. SortedSet接口

Vue.js 过渡

过渡 Vue 在插入、更新或者移除 DOM 时&#xff0c;提供多种不同方式的应用过渡效果。 Vue 提供了内置的过渡封装组件&#xff0c;该组件用于包裹要实现过渡效果的组件。 语法格式&#xff1a; <transition name "nameoftransition"><div></div&…

数据库(mysql)-连接嵌套查询-2

子查询 MySQL中的子查询&#xff08;Subquery&#xff09;是嵌套在其他SQL查询中的查询。子查询可以出现在SELECT、FROM或WHERE子句中&#xff0c;并用于返回将被用于外部查询的数据。子查询的结果可以是一个单一的值、一行、一列或多行多列的数据集。 单行单列查询 实例 #查…

2023 年网络安全热点技术发展态势

文章目录 前言一、人工智能信息技术迎来井喷式发展期二、零信任网络安全架构即将投入实际部署三、美国全面推动军政业务向云环境迁移四、专用太空软硬件与独立卫星网络并行发展五、量子信息技术与网络安全领域加速融合前言 在 2023 年取得进展的信息技术不在少数。从网络安全的…

基于51单片机低中高音7键电子琴音乐播放器

基于51单片机电子琴音乐播放器 &#xff08;仿真&#xff0b;程序&#xff0b;原理图&#xff0b;PCB&#xff0b;设计报告&#xff09; 功能介绍 具体功能&#xff1a; 1.可以使用按键切换音乐播放模式和弹奏模式&#xff1b; 2.LED灯显示在使用哪种模式&#xff1b; 3.音乐…