一张图理解JS的原型(prototype、_proto_、constructor的三角关系)

注意:前方高能预警,请认真仔细看完,阅读完后自己再次画下原型图,相信你一定会有更深刻的认识。(推荐炒鸡好用的画流程图的软件ProcessOn)

构造函数:function Foo ( ) { };

实例对象:let f1=new Foo;

let o1=new Foo;

每个函数都有 prototype 属性,除了 Function.prototype.bind(),该属性指向原型

每个对象都有 __proto__ 属性指向了创建该对象的构造函数的原型。其实这个属性指向了 [[prototype]],但是 [[prototype]] 是内部属性,我们并不能访问到,所以使用 _proto_ 来访问。

对象可以通过 __proto__ 来寻找不属于该对象的属性,__proto__ 将对象连接起来组成了原型链。

下面我们来解释上图的原型图的含义:

概念:

1、构造函数:用来初始化新创建的对象的函数是构造函数。在例子中,Foo()函数是构造函数。

2、实例对象:通过构造函数的new操作创建的对象是实例对象。可以用一个构造函数,构造多个实例对象。

function Foo(){};
var f1 = new Foo;
var f2 = new Foo;
console.log(f1 === f2);//false复制代码

3、原型对象及prototype:构造函数有一个prototype属性,指向实例对象的原型对象。通过同一个构造函数实例化的多个对象具有相同的原型对象。经常使用原型对象来实现继承。

function Foo(){};
Foo.prototype.a = 1;
var f1 = new Foo;
var f2 = new Foo;console.log(Foo.prototype.a);//1
console.log(f1.a);//1
console.log(f2.a);//1复制代码

4、constructor:原型对象有一个constructor属性,指向该原型对象对应的构造函数。由于实例对象可以继承原型对象的属性,所以实例对象也拥有constructor属性,同样指向原型对象对应的构造函数。

console.log(Foo.prototype.constructor === Foo);//true
console.log(f1.constructor === Foo);//true复制代码

5、_proto_:实例对象有一个proto属性,指向该实例对象对应的原型对象。

console.log(f1.__proto__ === Foo.prototype);//true复制代码

概念介绍完了,现在对图示的关系进行详细说明

【第一部分: Foo】

1、实例对象f1是通过构造函数Foo()的new操作创建的。构造函数Foo()的原型对象是Foo.prototype;实例对象f1通过__proto__属性也指向原型对象Foo.prototype。

console.log(f1.__proto === Foo.prototype);//true
复制代码

2、实例对象f1本身并没有constructor属性,但它可以继承原型对象Foo.prototype的constructor属性

console.log(Foo.prototype.constructor === Foo);//true
console.log(f1.constructor === Foo);//true
console.log(f1.hasOwnProperty('constructor'));//false复制代码

  下图是实例对象f1的控制台效果

【第二部分: Object】

1、Foo.prototype是f1的原型对象,同时它也是实例对象。实际上,任何对象都可以看做是通过Object()构造函数的new操作实例化的对象 所以,Foo.prototype作为实例对象,它的构造函数是Object(),原型对象是Object.prototype。相应地,构造函数Object()的prototype属 性指向原型对象Object.prototype;实例对象Foo.prototype的proto属性同样指向原型对象Object.prototype。

console.log(Foo.prototype.__proto__ === Object.prototype);//true
复制代码

2、实例对象Foo.prototype本身具有constructor属性,所以它会覆盖继承自原型对象Object.prototype的constructor属性。

console.log(Foo.prototype.constructor === Foo);//true
console.log(Object.prototype.constructor === Object);//true
console.log(Foo.prototype.hasOwnProperty('constructor'));//true复制代码

  下图是实例对象Foo.prototype的控制台效果

3、如果Object.prototype作为实例对象的话,其原型对象是什么,结果是null。我以为,这可能也是typeof null的结果是'object'的原因之一吧。

console.log(Object.prototype.__proto__ === null);//true
复制代码

【第三部分: Function】

1、前面已经介绍过,函数也是对象,只不过是具有特殊功能的对象而已。任何函数都可以看做是通过Function()构造函数的new操作实例化的结果。如果把函数Foo当成实例对象的话,其构造函数是Function(),其原型对象是Function.prototype;类似地,函数Object的构造函数也是Function(),其原型对象是Function.prototype。

console.log(Foo.__proto__ === Function.prototype);//true
console.log(Object.__proto__ === Function.prototype);//true复制代码

2、原型对象Function.prototype的constructor属性指向构造函数Function();实例对象Object和Foo本身没有constructor属性,需要继承原型对象Function.prototype的constructor属性。

console.log(Function.prototype.constructor === Function);//true
console.log(Foo.constructor === Function);//true
console.log(Foo.hasOwnProperty('constructor'));//false
console.log(Object.constructor === Function);//true
console.log(Object.hasOwnProperty('constructor'));//false
复制代码

3、所有的函数都可以看成是构造函数Function()的new操作的实例化对象。那么,Function可以看成是调用其自身的new操作的实例化的结果。所以,如果Function作为实例对象,其构造函数是Function,其原型对象是Function.prototype。

console.log(Function.__proto__ === Function.prototype);//true
console.log(Function.prototype.constructor === Function);//true
console.log(Function.prototype === Function.prototype);//true复制代码

4、如果Function.prototype作为实例对象的话,其原型对象是什么呢?和前面一样,所有的对象都可以看成是Object()构造函数的new操作的实例化结果。所以,Function.prototype的原型对象是Object.prototype,其原型函数是Object()。

console.log(Function.prototype.__proto__ === Object.prototype);//true
复制代码

总结:

【1】函数(Function也是函数)是new Function的结果,所以函数可以作为实例对象,其构造函数是Function(),原型对象是Function.prototype。

【2】对象(函数也是对象)是new Object的结果,所以对象可以作为实例对象,其构造函数是Object(),原型对象是Object.prototype

【3】Object.prototype的原型对象是null。



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

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

相关文章

Oracle触发器和MySQL触发器之间的区别

原文链接:http://blog.csdn.net/a19881029/article/details/37820363 -----------------------------------------------------------Oracle触发器格式:[plain] view plaincopyCREATE [OR REPLACE] TRIGGER trigger_name BEFORE|AFTER INSERT|UPDA…

下列选项中不符合python语言变量命名规则的是_学习Python第二日--基本概念和类型...

编程语言分类:解释型语言和编译型语言。解释型语言不会产生额外的文件,运行时一行一行的翻译。编译型语言需要产生一个额外的文件,是电脑能够识别的内容,运行后将产生额外的文件。 变量是可变的量,是它的值可以发生改变。变量的作用是保存值,保存的值可以是数据,而且保存…

HashMap死锁原因及替代方案

原文链接:http://blog.csdn.net/fhzaitian/article/details/51505516 ------------------------------------------------------------------------1、首先我们需要简单地了解一下HashMap数据结构 HashMap通常会用一个指针数组(假设为table[]&#xff09…

优化mysql数据库_MySQL数据库十大优化技巧

WEB开发者不光要解决程序的效率问题,对数据库的快速访问和相应也是一个大问题。希望本文能对大家掌握MySQL优化技巧有所帮助。1. 优化你的MySQL查询缓存在MySQL服务器上进行查询,可以启用高速查询缓存。让数据库引擎在后台悄悄的处理是提高性能的最有效方…

跋山涉水——深入 Redis 字典遍历

Redis 字典的遍历过程逻辑比较复杂,互联网上对这一块的分析讲解非常少。我也花了不少时间对源码的细节进行了整理,将我个人对字典遍历逻辑的理解呈现给各位读者。也许读者们对字典的遍历过程有比我更好的理解,还请不吝指教。一边遍历一边修改…

linux下VI模式中上下左右键和回退键出现字母

原文地址:http://blog.csdn.net/u012860950/article/details/50127779 ---------------------------------------------------------------- 1.编辑/etc/vim/vimrc.tiny 由于/etc/vim/vimrc.tiny的拥有者是root用户,所以要在root的权限下对这个文件进行修…

mysql数据库查询优化建议_mysql数据库查询优化的24条建议

MySQL是一个强大的开源数据库。随着MySQL上的应用越来越多,MySQL逐渐遇到了瓶颈。这里提供一些关于Mysql 数据库查询优化的24条优化建议,仅供参考。Mysql 查询优化1、使用慢查询日志,找出执行慢的查询。2、使用 EXPLAIN 来决定查询功能是否合…

常规sql读取CLOB

plsql下,普通sqlsql-cmd下总结: 常规的sql,查询clob字段,只能显示部分内容。 查clob内容select dbms_lob.substr(c_content) from table_content t dbms_lob.substr将大文本转换字符类型读出来.dbms_lob.substr的转换对字段conten…

精解 ES6箭头函数

🐱 个人主页:SHOW科技,公众号:SHOW科技 🙋‍♂️ 作者简介:2020参加工作,专注于前端各领域技术,共同学习共同进步,一起加油呀! 💫优质专栏&#x…

硬盘主引导记录详解

说明:硬盘主引导记录独立于操作系统,但又和操作系统息息相关——很多时候它又是由; 操作系统所提供的工具所生成(例外的情况是您使用了其他的分区工具,不过它又运行在; 什么操作系统中呢?;()。;; 如果您安装…

Oracle char varchar varchar2 nvarchar2 的区别

上面字符类型能保存多少个字符与oracle当前的字符集有关系。 select userenv(language) from dual; 假设长度2000字节, 如果字符集是16位编码的,ZHS16GBK,那么每个字符16位,2字节,所以可以容纳1000字符。 如果是32位编…

树莓派lnmp安装mysql_在树莓派上安装 LNMP

树莓派支持安装非常多的操作系统,如官方所展示:这里我选择了推荐的 Raspbian 系统,它基于 Debian,这就意味着我可以按照 Debian 的方式来安装软件。一、安装 Nginx0、先将系统更新到最新状态$ sudo apt-get update && sud…

openlayers5之热力图heatmap

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gisdoer/article/details/81745645 openlayers5之热力图 点击查看文章

maven项目在打war包时出现非法字符: '\ufeff' 解决方案

http://blog.csdn.net/qi_fei/article/details/61416319 --------------------------------------------问题描述: 开发工具MyEclipse 的总体开发环境,编码格式总体设置为UTF-8,在将web项目打包的时候出现:非法字符:\u…

0027-生成圆

题目 生成圆难度级别:A; 运行时间限制:1000ms; 运行空间限制:51200KB; 代码长度限制:2000000B 试题描述给你一些特殊的圆,每个这样的圆每秒可以产生一个普通的圆,如果给你…

mysql启多_MySQL启多个实例

很多朋友都想在一台服务器上运行多个MySQL Instance,究竟怎么做呢?首先要明晰几个原理, 简称为mysqld读取my.cnf的顺序:第一搜,首先读取/etc/my.cnf,多实例这个配置文件不会存在。:-(第二搜&…

数据连接池druid 和 大数据框架druid

叫druid的有两个开源项目。 一个是:Druid是一个JDBC组件,它包括三部分: DruidDriver 代理Driver,能够提供基于Filter-Chain模式的插件体系。 DruidDataSource 高效可管理的数据库连接池。 SQLParser 另一个是&#xff…

零基础入门深度学习(5) - 循环神经网络

往期回顾 在前面的文章系列文章中,我们介绍了全连接神经网络和卷积神经网络,以及它们的训练和使用。他们都只能单独的取处理一个个的输入,前一个输入和后一个输入是完全没有关系的。但是,某些任务需要能够更好的处理序列的信息&am…

sql排名名次分页mysql_mysql 实现排名及中文排序实例[分页累加行号]

/*排名相同情况下,优先按姓名排序*/SELECT t.name, t.company_name, rownum:rownum1 as rankNum, t.ss from (SELECT u.name, sci.company_name, rownum:0,(u.check_numu.online_hours) as ss FROM v_user uLEFT JOIN sys_company_info sci ON u.companyId sci.com…

世上最简单的mysql_史上最简单安装MySQL教程

1.安装MySQL很多都推荐在MySQL官网进行安装,我刚开始试的时候官网下载zip文件,打开完全找不到,踩坑了后面我发现了Windows简易安装,俗称傻子都会安装安装好了就会看到一个这个文件安装之前首先你的有没有这个你就无法安装,这个可以去这里进行下载安装好了就可以安装MySQL了因为…