帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
文章目录
- 1. 前言
- 2. _ _ proto _ _ 属性
- 3. prototype属性
- 4. constructor属性
- 5. 总结
提示:不要排斥,静下心来,认真读完,你就搞懂了!先看一份总结:
总结
- 我们需要牢记两点:①
__proto__
和constructor
属性是对象所独有的;②prototype
属性是函数所独有的,因为函数也是一种对象,所以函数也拥有__proto__
和constructor
属性。 __proto__
属性的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__
属性所指向的那个对象(父对象)里找,一直找,直到__proto__
属性的终点null,再往上找就相当于在null上取值,会报错。通过__proto__
属性将对象连接起来的这条链路即我们所谓的原型链。prototype
属性的作用就是让该函数所实例化的对象们都可以找到公用的属性和方法,即f1.__proto__ === Foo.prototype
。constructor
属性的含义就是指向该对象的构造函数,所有函数(此时看成对象了)最终的构造函数都指向Function。
1. 前言
作为一名前端工程师,必须搞懂JS中的prototype
、__proto__
与constructor
属性,相信很多初学者对这些属性存在许多困惑,容易把它们混淆,本文旨在帮助大家理清它们之间的关系并彻底搞懂它们。这里说明一点,__proto__
属性的两边是各由两个下划线构成(这里为了方便大家看清,在两下划线之间加入了一个空格:_ _proto_ _
,读作“dunder proto”,“double underscore proto”的缩写),实际上,该属性在ES标准定义中的名字应该是[[Prototype]]
,具体实现是由浏览器代理自己实现,谷歌浏览器的实现就是将[[Prototype]]
命名为__proto__
,大家清楚这个标准定义与具体实现的区别即可(名字有所差异,功能是一样的),可以通过该方式检测引擎是否支持这个属性:Object.getPrototypeOf({__proto__: null}) === null
。本文基于谷歌浏览器(版本 72.0.3626.121)的实验结果所得。
现在正式开始! 让我们从如下一个简单的例子展开讨论,并配以相关的图帮助理解:
function Foo() {...};
let f1 = new Foo();
- 1
- 2
以上代码表示创建一个构造函数Foo()
,并用new
关键字实例化该构造函数得到一个实例化对象f1
。这里稍微补充一下new操作符将函数作为构造器进行调用时的过程:函数被调用,然后新创建一个对象,并且成了函数的上下文(也就是此时函数内部的this是指向该新创建的对象,这意味着我们可以在构造器函数内部通过this参数初始化值),最后返回该新对象的引用,详细请看:详解JavaScript中的new操作符。虽然是简简单单的两行代码,然而它们背后的关系却是错综复杂的,如下图所示:
看到这图别怕,让我们一步步剖析,彻底搞懂它们!
图的说明:右下角为图例,红色箭头表示__proto__
属性指向、绿色箭头表示prototype
属性的指向、棕色实线箭头表示本身具有的constructor
属性的指向,棕色虚线箭头表示继承而来的constructor
属性的指向;蓝色方块表示对象,浅绿色方块表示函数(这里为了更好看清,Foo()仅代表是函数,并不是指执行函数Foo后得到的结果,图中的其他函数同理)。图的中间部分即为它们之间的联系,图的最左边即为例子代码。
2. _ _ proto _ _ 属性
首先,我们需要牢记两点:①__proto__
和constructor
属性是对象所独有的;② prototype
属性是函数所独有的。但是由于JS中函数也是一种对象,所以函数也拥有__proto__
和constructor
属性,这点是致使我们产生困惑的很大原因之一。上图有点复杂,我们把它按照属性分别拆开,然后进行分析:
第一,这里我们仅留下 __proto__
属性,它是对象所独有的,可以看到__proto__
属性都是由一个对象指向一个对象,即指向它们的原型对象(也可以理解为父对象),那么这个属性的作用是什么呢?它的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__
属性所指向的那个对象(可以理解为父对象)里找,如果父对象也不存在这个属性,则继续往父对象的__proto__
属性所指向的那个对象(可以理解为爷爷对象)里找,如果还没找到,则继续往上找…直到原型链顶端null(可以理解为原始人。。。),再往上找就相当于在null上取值,会报错(可以理解为,再往上就已经不是“人”的范畴了,找不到了,到此结束,null
为原型链的终点),由以上这种通过__proto__
属性来连接对象直到null
的一条链即为我们所谓的原型链。
其实我们平时调用的字符串方法、数组方法、对象方法、函数方法等都是靠__proto__
继承而来的。
3. prototype属性
第二,接下来我们看 prototype
属性:
prototype
属性,别忘了一点,就是我们前面提到要牢记的两点中的第二点,它是函数所独有的,它是从一个函数指向一个对象。它的含义是函数的原型对象,也就是这个函数(其实所有函数都可以作为构造函数)所创建的实例的原型对象,由此可知:f1.__proto__ === Foo.prototype
,它们两个完全一样。那prototype
属性的作用又是什么呢?它的作用就是包含可以由特定类型的所有实例共享的属性和方法,也就是让该函数所实例化的对象们都可以找到公用的属性和方法。任何函数在创建的时候,其实会默认同时创建该函数的prototype对象。
4. constructor属性
最后,我们来看一下 constructor
属性:
constructor
属性也是对象才拥有的,它是从一个对象指向一个函数,含义就是指向该对象的构造函数,每个对象都有构造函数(本身拥有或继承而来,继承而来的要结合__proto__
属性查看会更清楚点,如下图所示),从上图中可以看出Function这个对象比较特殊,它的构造函数就是它自己(因为Function可以看成是一个函数,也可以是一个对象),所有函数和对象最终都是由Function构造函数得来,所以constructor
属性的终点就是Function这个函数。
感谢网友的指出,这里解释一下上段中“每个对象都有构造函数”这句话。这里的意思是每个对象都可以找到其对应的constructor,因为创建对象的前提是需要有constructor,而这个constructor可能是对象自己本身显式定义的或者通过__proto__
在原型链中找到的。而单从constructor这个属性来讲,只有prototype对象才有。每个函数在创建的时候,JS会同时创建一个该函数对应的prototype对象,而函数创建的对象.__proto__ === 该函数.prototype,该函数.prototype.constructor===该函数本身
,故通过函数创建的对象即使自己没有constructor属性,它也能通过__proto__
找到对应的constructor,所以任何对象最终都可以找到其构造函数(null如果当成对象的话,将null除外)。如下:
5. 总结
总结一下:
- 我们需要牢记两点:①
__proto__
和constructor
属性是对象所独有的;②prototype
属性是函数所独有的,因为函数也是一种对象,所以函数也拥有__proto__
和constructor
属性。 __proto__
属性的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__
属性所指向的那个对象(父对象)里找,一直找,直到__proto__
属性的终点null,再往上找就相当于在null上取值,会报错。通过__proto__
属性将对象连接起来的这条链路即我们所谓的原型链。prototype
属性的作用就是让该函数所实例化的对象们都可以找到公用的属性和方法,即f1.__proto__ === Foo.prototype
。constructor
属性的含义就是指向该对象的构造函数,所有函数(此时看成对象了)最终的构造函数都指向Function。
本文就此结束了,希望对那些对JS中的prototype
、__proto__
与constructor
属性有困惑的同学有所帮助。
最后,感谢这两篇博文,本文中的部分内容参考自这两篇博文:
https://www.cnblogs.com/xiaohuochai/p/5721552.html
https://www.cnblogs.com/Narcotic/p/6899088.html
http://www.taodudu.cc/news/show-2887850.html
相关文章:
- 旧金山犯罪预测与可视化分析
- 2022.10.28 英语背诵
- IT行业人才招聘回顾与展望
- 《机器学习实战》学习笔记(四):基于概率论的分类方法 - 朴素贝叶斯
- 转贴:ubuntu 7.10 常用软件与编程环境搭建
- 简化控制器内容
- 东邪、西毒、南帝、北丐、中神通五大操作系统之华山论剑(独评)
- kafka 0.10.0 producer java代码实现
- beaglebone black下接nrf24l01与RFID标签的通信(基于EZSDK linux平台)
- 阿萨德撒的撒的撒的
- Android以太坊钱包全部功能-基于web3j实现
- ARM Linux 内核 panic 之cache 一致性 ——cci-400 cache一致互联
- Selenium 爬虫应用的学习
- am335x linux内核烧写_am335x文件系统烧写问题
- 小爱同学指令大全_小爱同学有哪些隐藏功能?小爱同学实用隐藏功能大汇总
- 小天才z6官方禁用怎么关闭_我告诉你小天才z6隐藏功能
- 你不能不知道的荣耀V40隐藏功能
- 科学计算机隐藏功能,经常用手机计算器的抓紧看看,原来还隐藏着3个功能,涨知识了...
- 原来华为手机的拨号键盘除了打电话,还有这些隐藏功能,涨知识了
- vivo计算机的隐藏功能介绍,六大vivo隐藏黑科技功能 绝对有你不知道的
- 华为android10手机隐藏小游戏,华为手机10个实用好玩的隐藏功能
- 别说华为语音助手不智能了,这3大隐藏功能都知道吗?实用又贴心
- vue实现select下拉显示隐藏功能【详细功能拓展】
- MFC对话框部分区域的显示和隐藏功能的实现
- 手机计算机藏应用,手机“计算器”隐藏功能,一键把隐私照片加密
- 三星note20u计算机功能,三星Note20Ultra隐藏功能有哪些-有哪些使用技巧
- 酷开系统这些隐藏功能你用过几个?
- iOS内容含有隐藏功能、第三方支付等被拒4次的心路历程
- 三星note20u计算机功能,三星Note20Ultra隐藏功能有哪些-藏功能操作方法
- casio计算机隐藏游戏fx-82ES,CASIOlowbar;fx-82ES计算器隐藏功能
帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)相关推荐
- (转)帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
文章目录 1. 前言 2. _ _ proto _ _ 属性 3. prototype属性 4. constructor属性 5. 总结 提示:不要排斥,静下心来,认真读完,你就搞懂了!(可以先看一下 ...
- 这一篇彻底搞懂JS中的prototype、__proto__与constructor真的很好
文章目录 1. 前言 2. _ _ proto _ _ 属性 3. prototype属性 4. constructor属性 5. 总结 提示:不要排斥,静下心来,认真读完,你就搞懂了!(可以先看一下 ...
- 彻底搞懂 JS 中 this 机制
彻底搞懂 JS 中 this 机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.com/jasonGeng88/blog 目录 this 是什么 this 的四种绑定规 ...
- 彻底搞懂 JS 中 this 机制 1
彻底搞懂 JS 中 this 机制 摘要:本文属于原创,欢迎转载,转载请保留出处:https://github.com/jasonGeng88/blog 目录 this 是什么 this 的四种绑定规 ...
- 一文搞懂JS中的赋值·浅拷贝·深拷贝
前言 为什么写拷贝这篇文章?同事有一天提到了拷贝,他说赋值就是一种浅拷贝方式,另一个同事说赋值和浅拷贝并不相同.我也有些疑惑,于是我去MDN搜一下拷贝相关内容,发现并没有关于拷贝的实质概念,没有办法只 ...
- JS中的prototype、__proto__与constructor
作为一名前端工程师,必须搞懂JS中的prototype.__proto__与constructor属性,相信很多初学者对这些属性存在许多困惑,容易把它们混淆,本文旨在帮助大家理清它们之间的关系并彻底搞 ...
- JS中的prototype、__proto__与constructor(图解)
作为一名前端工程师,必须搞懂JS中的prototype.__proto__与constructor属性,相信很多初学者对这些属性存在许多困惑,容易把它们混淆,本文旨在帮助大家理清它们之间的关系并彻底搞 ...
- 彻底搞懂javascript中的replace函数
javascript这门语言一直就像一位带着面纱的美女,总是看不清,摸不透,一直专注服务器端,也从来没有特别重视过,直到最近几年,javascript越来越重要,越来越通用.最近和前端走的比较近,借此 ...
- 一文搞懂产品中的搜索设计
搜索功能是我们日常生活中接触最多的功能之一,它更够很好的提高用户使用产品的效率,用户对搜索功能的依赖性也比较大,所以设计好搜索功能将会很大程度上提高用户体验.本文作者通过分享这篇文章,帮我们搞懂产品中 ...
最新文章
- three.js 背景图片
- 分布式任务队列 Celery — 详解工作流
- python中一共有多少个关键字-Python 为什么会有命名关键字参数?
- dede php 常用,dede cms常用标签汇总 收藏版
- Linq的简介和基础知识学习
- 动态生成Repeater
- 20 款优秀的数据可视化工具,总有一款你用的到!
- leetcode 354. 俄罗斯套娃信封问题(dp+二分)
- java计算器 运算符优先级_跪求大神帮忙,怎样在java 计算器中实现,四则运算优先级;...
- Unity 5.x---00使用重力
- SQLServer表字段默认值相关信息的获取方法
- 百花开放笑声甜_“开源萌宠”庆六一
- 逻辑回归算法深度思考-优点和缺点
- VS2017下载地址
- C/C++ 机房预约系统
- [附源码]计算机毕业设计Python架构的博客平台设计(程序+源码+LW文档)
- 解决每次运行Xcode都需要输入密码问题
- C语言练习题的错题集
- 程序员的 100款代码表白特效,一个比一个浪漫
- iic键盘驱动 android,IIC的键盘驱动
热门文章
- WEBGIS开发 常用开发功能简介 数据处理 标绘 业务数据可视化 视频融合 Cesium EarthSDK
- 黑盒、白盒、灰盒测试
- 计算机网络常见面试问题和解析
- 你连HTTPS 原理都不懂,还给我讲“中间人攻击”
- MD5加密算法的原理和应用
- 大学四年,因为这些网站,他顺利拿下字节跳动的offer!
- 谈谈SVM和SVR的区别
- 2021年江西省上饶市高考成绩查询,2021年上饶高考状元名单公布,上饶文理科状元是谁多少分...
- 自己编写自动同步脚本
- linux音源管理 二维表,Oracle【二维表管理:约束】