JS原型链与instanceof底层原理

转载自  JS原型链与instanceof底层原理

一、问题:

instanceof 可以判断一个引用是否属于某构造函数;

另外,还可以在继承关系中用来判断一个实例是否属于它的父类型。

老师说:instanceof的判断逻辑是: 从当前引用的proto一层一层顺着原型链往上找,能否找到对应的prototype。找到了就返回true。

如果没有发生继承关系,这个逻辑自然是没有疑惑的。

但是,利用原型继承,切断了原来的prototype的指向,而指向了一个新的对象,这时instanceof又是如何进行判断的呢?

本文通过代码与画图分析instanceof的底层原理,借此复习原型链的知识。


二、instanceof底层是如何工作的:


function instance_of(L, R) {//L 表示左表达式,R 表示右表达式 var O = R.prototype;   // 取 R 的显示原型 L = L.__proto__;  // 取 L 的隐式原型while (true) {    if (L === null)      return false;   if (O === L)  // 当 O 显式原型 严格等于  L隐式原型 时,返回truereturn true;   L = L.__proto__;  }}

三、案例:未发生继承关系时

function Person(name,age,sex){this.name = name;this.age = age;this.sex = sex;}function Student(score){this.score = score;}var per = new Person("小明",20,“男”);var stu = new Student(98);console.log(per instanceof Person);  // trueconsole.log(stu instanceof Student);  // trueconsole.log(per instanceof Object);  // trueconsole.log(stu instanceof Object);  // true

1、下图1是未发生继承关系时的原型图解:

 

图1 未发生继承关系时的原型图解

2、instanceof的工作流程分析

首先看per instanceof Person

 function instance_of(L, R) { // L即per ;  R即Personvar O = R.prototype; //O为Person.prototypeL = L.__proto__;       // L为per._proto_while (true) {    //执行循环if (L === null)   //不通过return false;   if (O === L)       //判断:Person.prototype ===per._proto_?return true;  //如果等于就返回true,证明per是Person类型L = L.__proto__;                   }}         

执行per instanceof Person ,通过图示看出 Person.prototype ===per.proto 是成立的,所以返回true,证明引用per是属于构造函数Person的。

接下来再看 per instanceof Object

 function instance_of(L, R) { //L即per ;  R即Object        var O = R.prototype;  //O为Object.prototype        L = L.__proto__;    // L为per._proto_             while (true) {     //执行循环                   if (L === null)   //不通过                            return false;                      if (O === L)   //Object .prototype === per._proto_?  不成立**return true;                         L = L.__proto__;   //令L为 per._proto_ ._proto_ ,**//即图中Person.prototype._proto_指向的对象//接着执行循环,//到Object .prototype === per._proto_ ._proto_  ?//成立,返回true}}

四、案例:发生继承关系时

 function Person(name,age,sex){this.name = name;this.age = age;this.sex = sex;}function Student(name,age,sex,score){Person.call(this,name,age,sex);  this.score = score;}Student.prototype = new Person();  // 这里改变了原型指向,实现继承var stu = new Student("小明",20,"男",99); //创建了学生对象stuconsole.log(stu instanceof Student);    // trueconsole.log(stu instanceof Person);    // trueconsole.log(stu instanceof Object);    // true

1、下图2是发生继承关系后的原型图解

 

图2 发生继承关系后的原型图解

2、instanceof的工作流程分析

首先看 stu instanceof Student

 function instance_of(L, R) { //L即stu ;  R即Studentvar O = R.prototype;  //O为Student.prototype,现在指向了perL = L.__proto__;    //L为stu._proto_,也随着prototype的改变而指向了perwhile (true) {    //执行循环if (L === null)  //不通过return false;   if (O === L)    //判断: Student.prototype ===stu._proto_?return true;  //此时,两方都指Person的实例对象per,所以trueL = L.__proto__;                   }} 

所以,即使发生了原型继承,stu instanceof Student 依然是成立的。

接下来看 stu instanceof Person,instanceof是如何判断stu继承了Person

 function instance_of(L, R) { // L即stu ;  R即Person        var O = R.prototype; // O为Person.prototype     L = L.__proto__;   //L为stu._proto_,现在指向的是per实例对象while (true) {   // 执行循环                   if (L === null)   //不通过                            return false;                    if (O === L)    //判断:   Person.prototype === stu._proto_ ?      return true;   //此时,stu._proto_ 指向per实例对象,并不满足L = L.__proto__;  //令L=  stu._proto_._proto_,执行循环}                      //stu._proto_ ._proto_,看图示知:}                        //指的就是Person.prototype,所以也返回true

stu instanceof Person返回值为true,这就证明了stu继承了Person。

stu instanceof Object也是同理的,根据图示即可轻易得出。

五、结论

1、instanceof 的作用

用于判断一个引用类型是否属于某构造函数;

还可以在继承关系中用来判断一个实例是否属于它的父类型。

2、和typeof的区别:

typeof在对值类型number、string、boolean 、null 、 undefined、 以及引用类型的function的反应是精准的;但是,对于对象{ } 、数组[ ] 、null 都会返回object

为了弥补这一点,instanceof 从原型的角度,来判断某引用属于哪个构造函数,从而判定它的数据类型。


 

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

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

相关文章

正则之注册登录

不久前写了个登录注册的网站,因为未对其做出限制,所以,随便你输入什么都可以注册成功,遂想怎么通过js规定注册的账号 我的要求是: 一:输入框不能为空,不能太长也不能太短 二: 1、注…

猿创征文|从酒店前台收银到软件研发教学主管到技术经理之路~

大家好,我是雄雄。 内容先知👉前言☝酒店收银🤨项目组长🤜OA管理系统🤜酒店管理系统👨‍🏫软件研发讲师📌学术主管👨‍💻技术经理👉项目情况&…

微服务~分布式事务里的最终一致性

本地事务ACID大家应该都知道了,统一提交,失败回滚,严格保证了同一事务内数据的一致性!而分布式事务不能实现这种ACID,它只能实现CAP原则里的某两个,CAP也是分布式事务的一个广泛被应用的原型,CA…

JavaFX仿windows文件管理器目录树

一、windows文件管理器目录树 二、代码 /** To change this license header, choose License Headers in Project Properties.* To change this template file, choose Tools | Templates* and open the template in the editor.*/ package cn.util;import imagemanagesystem.…

开源纯C#工控网关+组态软件(三)加入一个新驱动:西门子S7

一、 引子 首先感谢博客园:第一篇文章、第一个开源项目,算是旗开得胜。可以看到,项目大部分流量来自于博客园,码农乐园,名不虚传^^。 园友给了我很多支持,并提出了很好的改进意见。现加入屏幕分辨率自适应…

有没有完全自助的国产化数据库技术?

大家好,我是雄雄。 SPL资料 SPL官网SPL下载SPL源代码 前段时间世界部分地区不断的起冲突,Oracle宣布“暂停在俄罗斯的所有业务”,相信大家的心情绝不是隔岸观火,而是细思恐极。 数据库号称IT领域三大核心之一(其他两…

我为啥不看好ServiceMesh

转载自 我为啥不看好ServiceMesh 前言 今年,ServiceMesh(服务网格)概念在社区里头非常火,有人提出2018年是ServiceMesh年,还有人提出ServiceMesh是下一代的微服务架构基础。作为架构师,如果你现在还不了解ServiceMesh的话&…

ASP.NET Core 2.0 支付宝当面付之扫码支付

前言 自从微软更换了CEO以后,微软的战略方向有了相当大的变化,不再是那么封闭,开源了许多东西,拥抱开源社区,.NET实现跨平台,收购xamarin并免费提供给开发者等等。我本人是很喜欢.net的,并希望.…

Git使用教程:最详细、最傻瓜、最浅显、真正手把手教

转载自 Git使用教程:最详细、最傻瓜、最浅显、真正手把手教 一:Git是什么? Git是目前世界上最先进的分布式版本控制系统。 工作原理 / 流程: Workspace:工作区 Index / Stage:暂存区 Repository&…

【git】如何在github上推送并部署自己的项目

口令快捷 git add . git commit --m "XXXX" git remote add origin https://github.com/lifeload/new-problem.git git push -f origin master修改或删除文件 git add 对应文件/. git commit -m “xxx” git push origin master 1、上传代码 2、设置,建立…

一起聊聊Microsoft.Extensions.DependencyInjection

Microsoft.Extensions.DependencyInjection在github上同样是开源的,它在dotnetcore里被广泛的使用,比起之前的autofac,unity来说,它可以说是个包裹,或者叫适配器,它自己提供了默认的DI实现,同时也支持第三方…

【git】如何给github绑定ssh

首先在git上输入 : ssh-keygen 会在c盘的用户账号的文件夹.ssh上生成两个密钥 (如果没有生成,请注意自己是否按了enter,出现一个小方框为止) 将.pug用笔记本打开 全选复制 来到github的设置上 将刚刚复制的东西黏…

【杭州】Hack for Cloud Beginner微软黑客松大赛

在这美丽的西子湖畔,我们欢迎各行各业的开发者参与此次Hack for Cloud Beginner微软黑客松大赛。我们致力于为开发者们提供在技术、社区领域中的交流平台,重在参与,意于创新。 此次黑客松大赛将于10月22日在中国杭州拉开帷幕,参与…

Java高级开发必会的50个性能优化的细节(珍藏版)

转载自 Java高级开发必会的50个性能优化的细节(珍藏版) 在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身。养成良好的编码习惯非常重要,能够显著地提升程序性能。 ● 1. 尽量在合适的场合使用单例…

从0部署一个动态网站

准备:购买域名和服务器 下载软件:服务器上下载宝塔面板和xampp 首先区分动态网站和静态网站区别:动态网站是指数据可以交互的,根据不同的人出现不同的页面,要用到数据库和php。登录注册是动态网站最基础的部分 而静态…

最新的.NET Framework聚焦于改进可访问性

Microsoft宣布预发布.NET Framework 4.7.1,其中包括了各种全面的改进。这里,我们关注一下在WPF应用可访问性上所做的改进。改进的设想针对领域是屏幕报读器(Screen Reader)和高对比度场景。Microsoft的Preeti Krishna表示&#xf…

ImageSharp一个专注于NetCore平台图像处理的开源项目

今天大家分享的是一个专注于NetCore平台图像处理的开源项目,老实说为这篇文章取名字想了5分钟,可能是词穷亦或是想更好的表达出这款开源项目的作用;这个项目在图像处理方面有很多功能,如:缩放,裁剪&#xf…

关于 JVM 内存的 N 个问题

转载自 关于 JVM 内存的 N 个问题 JVM的内存区域是怎么划分的? JVM的内存划分中,有部分区域是线程私有的,有部分是属于整个JVM进程;有些区域会抛出OOM异常,有些则不会,了解JVM的内存区域划分以及特征&am…

RedHat宣布支持Azure、.Net Core 2.0和SQL Server 2017

近期,Microsoft和RedHat宣布支持在Red Hat OpenShift上运行Windows容器。此次宣布所针对的主要场景,是让Linux和Windows容器工作于同一集群中。这将使具有混杂环境的企业无需分别运行Windows集群和Linux集群,企业可以迁移到基于容器的同一种架…

安装webpack

全局安装 npm install -g webpack 项目中安装 npm install --save-dev webpack 安装webpack遇到个坑,问题的话应该是项目使用的是webpack2.X版本,这样就会覆盖之前的版本,导致项目配置错误。 所以最好不要用全局安装 cd进相关文件夹后 cnpm …