Javascript深入__proto__和prototype的区别和联系
有一个一个装逼的同事,写了一段代码
function a(){}
a.__proto__.__proto__.__proto__
然后问我,下面这个玩意a.__proto__.__proto__.__proto__是啥,然后我一脸懵逼,prototype还知道一点,这个__proto__,还来三个,是个什么鬼。于是我一直不能放下这个问题,虽然我很懒,很不喜欢费脑子,但是这个坎还是过不去,最近两天研究了大半天,就有了这篇文章。
我先说出答案, 上面的值为 null。我还很负责的告诉你,下面的_a.__proto__.__proto__.__proto__也是null
function a(){}
var _a = new a();
_a.__proto__.__proto__.__proto__
先来一张非常经典的图,真的是非常经典,你看懂他,你就懂了整个世界,然后整个世界就等着你去拯救整个世界。
)
正文之前,__proto__和prototype
都谁有的问题
typeof === object的有__proto__ , null和undefined都没有
typeof === function的有__proto__和prototype
__proto__ 是什么__proto__ 一般情况指向的是该对象的构造函数的prototype,一般情况,因为还有很二般的情况。
先来看个简单的例子, 下面的输出是true
function a(){}
var _a = new a()
console.log(_a.__proto__ === a.prototype)
那我问_a.__proto__.__proto__为什么呢,你会这么推导么,
依据上面_a.__proto__ === a.prototype,那么_a.__proto__.__proto__就等同a.prototype.__proto__ , 那么我们就再推到等于 a.prototype.constructor.prototype,然后你去一比,结果是false。
_a.__proto__.__proto__ === a.prototype.constructor.prototype
// false
几条规则
这个先不纠结, 我们先看看上图,我们先得知道或者记住这几个规则
Object.prototype.__proto__ === null
不要纠结,铁律Object.__proto__ === Function.prototype
Object,Number, Error等等这些函数都是Function创建的,下面就说明
这些的constructor就是Function,这里比较有意思的就是 Function.constructor也是Function。
那就有Object.__proto__ === Function.prototype === Function.__proto__Object.constructor.prototype === Function.prototype
// true
Function.constructor === Function
// trueFunction.prototype.__proto__ === Object.prototype
这个就是这样的设计,Function.prototype.constructor === Object
// false进入正题
有这几个基本东西,我们就可以来推导了。
先看下面的代码,
js 我们来推到 aaa.__proto__.__proto__.__proto__
function aaa(){}
var _aaa = new aaa()
aaa.__proto__
aaa构造函数是Functionaaa.constructor === Functionaaa.__proto__ === Function.prototypeaaa.__proto__.__proto__aaa.__proto__.__proto__ === Function.prototype.__proto__
依据Function.prototype.__proto__ === Object.prototypeaaa.__proto__.__proto__ === Function.prototype.__proto__ === Object.prototypeaaa.__proto__.__proto__.__proto__aaa.__proto__.__proto__.__proto__ === Object.prototype.__proto__
依据Object.prototype.__proto__ === nullaaa.__proto__.__proto__.__proto__ === null
还是上面代码,我们接着推导_aaa.__proto__.__proto__.__proto__
_aaa.__proto__
_aaa的构造函数是 aaa_aaa.constructor === aaa_aaa.__proto__ === _aaa.constructor.prototype_aaa.__proto__ === aaa.prototype_aaa.__proto__.__proto___aaa.__proto__.__proto__ === aaa.prototype.__proto__
参考图,Foo.prototype.__proto__ === Object.prototype_aaa.__proto__.__proto__ === aaa.prototype.__proto__ === Object.protype_aaa.__proto__.__proto__.__proto___aaa.__proto__.__proto__.__proto__ === Object.protype.__proto__
依据Object.prototype.__proto__ === null_aaa.__proto__.__proto__ === null
正文延伸, 加上继承关系
我们再来看看,带继承关系的
function aaa(){}
function bbb(){}
bbb.prototype = new aaa()
var _bbb = new bbb();
bbb.__proto__.__proto__.__proto__ === null
这个没啥好说,
关键来看看 bbb.prototype.__proto__.__proto__.__proto__
bbb.prototype.__proto__bbb.prototype.__proto__ === bbb.prototype.constructor.prototype
bbb.prototype的原型是 aaa的实例, bbb原型的构造函数就是aaa,所以bbb.prototype.__proto__ === aaa.prototypebbb.prototype.__proto__.__proto__bbb.prototype.__proto__.__proto__ === aaa.prototype.__proto__
参考图,Foo.prototype.__proto__ === Object.prototypebbb.prototype.__proto__.__proto__ === Object.prototypebbb.prototype.__proto__.__proto__bbb.prototype.__proto__.__proto__ .__proto__=== Object.prototype.__proto__ === null
再来看看_bbb.__proto__.__proto__.__proto__ .__proto__
_bbb.__proto___bbb.__proto__ === bbb.prototype- _bbb.proto.proto
_bbb.__proto__.__proto__ === bbb.prototype._proto__ === bbb.prototype.constructor.prototype === aaa.prototype - _bbb.proto.proto.proto
_bbb.__proto__.__proto__.__proto__ === aaa.prototype.__proto__
参考图Foo.prototype.__proto__ === Object.prototype_bbb.__proto__.__proto__.__proto__ === aaa.prototype.__proto__ === Object.prototype _bbb.__proto__.__proto__.__proto__.__proto___bbb.__proto__.__proto__.__proto__.__proto__ === Object.prototype.__proto__ === null
正文 再加量
看看如下代码
function aaa(){}
var _aaa = new aaa()
function bbb(){}
bbb.prototype = new aaa();
var _bbb = new bbb();
function ccc(){}
ccc.prototype = new bbb()
var _ccc = new ccc()
我们再来分析_ccc的prototype和__proto__,你们会说,你有完没完
,那我就不分析了,我来推断:
推断:
任何自定义的function本身,三次
__proto__必然是null,也就是往上找三代
包括Function,Object, Error等等
Fucntion.proto 看图,依据Object.__proto__ === Function.prototype === Function.__proto__
我们来推导Function.__proto__.__proto__ .__proto__
第一步:Function.__proto__ === Function.prototype
第二步:Function.__proto__.__proto__ === Function.prototype.__proto__ === Object.protetype
第三步:Function.__proto__.__proto__ .__proto__ === Object.protetype.__proto__ === null
都是Function构造出来的
我们来测试一下cccccc.__proto__.__proto__.__proto__ === null // true继承关系的function fn,假设继承次数为n,
_fn = new fn();
那么_fn.__protot__[3 + n] === null
_ccc应该是3+2就是5次_ccc.__proto__.__proto__.__proto__.__proto__.__proto__ === null // true继承关系的function fn,假设继承次数为n
推到fn.prototype.__proto__[3+n-1]
ccc应该是 4次__proto__ccc.prototype.__proto__.__proto__.__proto__.__proto__ === null // true当然上面关联的关系,就自己慢慢看吧
正文之外, class
下面的代码也是遵守规则,至于为什么,问自己喽。
class aaa {}
class bbb extends aaa{}
class ccc extends bbb{};
var _ccc = new ccc()
关于Number,Boolen, String,Function, Date, Array, RegExp等的__proto__和prototype.proto`
__proto__
因为这些都是Function创建出来的函数,__proto__在函数上时就是表示构造函数的prototype,所以.__proto__ === .constrcutor.prototype === Function.prototype.prototype.__proto__这些老骨头不遵循__proto__为构造函数的prototype
在上面提到过了,Function.prototype.__proto__ === Object.prototype,
类推,这些内置的老骨头的.prototype.__proto__ === Object.prototype
## 总结
总结, 特别需要记忆的:
Object.prototype.__proto__ === nullFunction.prototype.__proto__ === Object.prototype
内置Number,Boolen, String,Function, Date, Array, RegExp等一样Object.__proto__ === Function.prototype === Function.__proto__
联系2,这些东西都是Function创建出来的Math, JSON的__ptoto__是 Object.prototype
typeof 可以看出来这两个是object,而不是Function- function a(){} 这样创建出来,没有继承关系的函数
a.prototype.__proto__ === Object.prototype - 有继承关系的function看上面的推断
- 对象字面量和new Object() 比如, var a ={}, b = new Object(), c = [];
a.__proto__ === a.constructor.prototype === Object.protypea.__proto__.__proto__ === Object.protype.__proto__ === null - 基本数据类型string,number,boolean,比如 var a = '', b=10, c= false,
b.__proto__ === b.constructor.prototype === Number.prototypeb.__proto__.__proto__ === Number.prototype.__proto__ === Object.prototypeb.__proto__.__proto__.__proto__ === Object.prototype.__proto__ === null - null和undefined没有__proto__
最终
- 看图
- 浏览器输入
xx.__proto__或者xx.prototype自己看去
Javascript深入__proto__和prototype的区别和联系的更多相关文章
- 【JavaScript】__proto__和prototype的区别和联系【整理】
var person={name:'ninja'}; person.prototype.sayName=function(){ return this.name; } Chrome运行结果: 提示找不 ...
- 谈谈__proto__和prototype的区别
我想javascript中的原型链一直想很多初学javascript的同学感到非常的困惑,今天看了一些文章,结合自己的理解,把原型链这个东西从新来整理一下,如有不对之处,望大家帮忙指出. 首先,我们应 ...
- js中__proto__和prototype的区别和关系? 这样好理解多了
原型的概念 真正理解什么是原型是学习原型理论的关键.很多人在此产生了混淆,没有真正理解,自然后续疑惑更多. 首先,我们明确原型是一个对象,其次,最重要的是, Every function has a ...
- JavaScript中__proto__与prototype的关系
一.所有构造器/函数的__proto__都指向Function.prototype,它是一个空函数(Empty function) 1 2 3 4 5 6 7 8 9 Number.__proto__ ...
- js中__proto__和prototype的区别和关系?
_proto__(隐式原型)与prototype(显式原型)1.是什么 显式原型 explicit prototype property: 每一个函数在创建之后都会拥有一个名为prototype的属性 ...
- 再说javascript 的__proto__ 和prototype 属性
过了一段时间,没写 原生的 javascript 的了,感觉天天在用框架写代码,框架写代码完全限定死了你所需要思考的东西,只是在处理一些业务逻辑,真正的代码 都感觉不会写了. 突然发现,框架用的不熟悉 ...
- JavaScript的__proto__、prototype和继承
JavaScript也是可以“继承”的! 各位看官或是好奇,或是一知半解.什么是prototype,__proto__,constructor.哪种继承方式好.今天就在这交流交流. 什么是protot ...
- JavaScript中__proto__与prototype的关系(转)
一.所有构造器/函数的__proto__都指向Function.prototype,它是一个空函数(Empty function) 1 2 3 4 5 6 7 8 9 Number.__proto__ ...
- 深入__proto__和prototype的区别和联系
前话 有一个一个装逼的同事,写了一段代码 function a(){} a.__proto__.__proto__.__proto__ 然后问我,下面这个玩意a.__proto__.__proto__ ...
随机推荐
- UVA - 1160(简单建模+并查集)
A secret service developed a new kind of explosive that attain its volatile property only when a spe ...
- OPENGL绘制文字
OPENGL没有提供直接绘制文字的功能,需要借助于操作系统. 用OPENGL绘制文字比较常见的方法是利用显示列表.创建一系列显示列表,每个字符对应一个列表编号.例如,'A'对应列表编号1000+'A' ...
- ASP.NET Core 如何设置发布环境
在ASP.NET Core中自带了一些内置对象,可以读取到当前程序处于什么样的环境当中,比如在ASP.NET Core的Startup类的Configure方法中,我们就会看到这么一段代码: publ ...
- Java Activiti6.0 spring5 SSM 工作流引擎 审批流程 java项目框架
1.模型管理 :web在线流程设计器.预览流程xml.导出xml.部署流程 2.流程管理 :导入导出流程资源文件.查看流程图.根据流程实例反射出流程模型.激活挂起 3.运行中流程:查看流程信息.当前任 ...
- Ubuntu下配置jdk和tomcat
一.配置jdk 更新系统 apt-get update 添加ppa add-apt-repository ppa:webupd8team/java 开始安装 apt-get install oracl ...
- 虚拟机系统ubuntu12.04(内网环境下的虚拟主机)开启远程连接访问
一.工具准备: 1.内网虚拟机Ubuntu12.04系统主机一台,开放端口为:29999 2.远程连接软件:mobaxterm 二.开启步骤: 1.查看端口状态信息: netstat -antl | ...
- IE浏览器中找不到开发者工具
ie浏览器不知道什么原因开发者工具不见了.打开以后在任务栏中显示打开了控制台,但是看不到. 解决方法 : F12 打开开发者工具后,按下 “ Ctrl + P ”
- js获取dom元素的子元素,父元素,兄弟元素小记
原生jsvar a = document.getElementById("dom"); del_space(a); //清理空格 var b = a.childNodes; //获 ...
- 前端基础-jQuery的内容之选择器
阅读目录 ID选择器 类选择器 元素选择器 通配符选择器 层级选择器 基本筛选器 内容筛选器 可见性筛选器 属性筛选器 子元素筛选器 表单元素筛选器 表单对象筛选器 this和$(this) 一.jQ ...
- golang学习总结
目录 1. 初识go语言 1.1 Hello World 1.2 go 数据类型 布尔: 整型: 浮点型: 字符类型 字符串型: 复数类型: 1.3 变量常量 局部变量: 全局变量 常量 1.5 字符 ...