前话

有一个一个装逼的同事,写了一段代码

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

几条规则

这个先不纠结, 我们先看看上图,我们先得知道或者记住这几个规则

  1. Object.prototype.__proto__ === null

    不要纠结,铁律
  2. 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
// true
  1. Function.prototype.__proto__ === Object.prototype

    这个就是这样的设计,
Function.prototype.constructor === Object
// false
  1. 自定义函数,没有修改默认原型的情况下,比如 function Person(){},

    Person.prototype.__proto__ === Object.prototype

    Person.constructor === Function

    对比3一看,Function和构造函数是Function的Person,他们prototype.__proto__的指向是一样的。

进入正题

有这几个基本东西,我们就可以来推导了。

先看下面的代码,

js 我们来推到 aaa.__proto__.__proto__.__proto__

function aaa(){}
var _aaa = new aaa()
  1. aaa.__proto__

    aaa构造函数是Function

    aaa.constructor === Function

    aaa.__proto__ === Function.prototype

  2. aaa.__proto__.__proto__

    aaa.__proto__.__proto__ === Function.prototype.__proto__

    依据 Function.prototype.__proto__ === Object.prototype

    aaa.__proto__.__proto__ === Function.prototype.__proto__ === Object.prototype

  3. aaa.__proto__.__proto__.__proto__

    aaa.__proto__.__proto__.__proto__ === Object.prototype.__proto__

    依据 Object.prototype.__proto__ === null

    aaa.__proto__.__proto__.__proto__ === null

还是上面代码,我们接着推导_aaa.__proto__.__proto__.__proto__

  1. _aaa.__proto__

    _aaa的构造函数是 aaa

    _aaa.constructor === aaa

    _aaa.__proto__ === _aaa.constructor.prototype

    _aaa.__proto__ === aaa.prototype

  2. _aaa.__proto__.__proto__

    _aaa.__proto__.__proto__ === aaa.prototype.__proto__

    参考图,Foo.prototype.__proto__ === Object.prototype

    _aaa.__proto__.__proto__ === aaa.prototype.__proto__ === Object.protype

  3. _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__

  1. bbb.prototype.__proto__

    bbb.prototype.__proto__ === bbb.prototype.constructor.prototype

    bbb.prototype的原型是 aaa的实例, bbb原型的构造函数就是aaa,所以

    bbb.prototype.__proto__ === aaa.prototype

  2. bbb.prototype.__proto__.__proto__

    bbb.prototype.__proto__.__proto__ === aaa.prototype.__proto__

    参考图,Foo.prototype.__proto__ === Object.prototype

    bbb.prototype.__proto__.__proto__ === Object.prototype

  3. bbb.prototype.__proto__.__proto__

    bbb.prototype.__proto__.__proto__ .__proto__=== Object.prototype.__proto__ === null

再来看看_bbb.__proto__.__proto__.__proto__ .__proto__

  1. _bbb.__proto__

    _bbb.__proto__ === bbb.prototype
  2. _bbb.proto.proto

    _bbb.__proto__.__proto__ === bbb.prototype._proto__ === bbb.prototype.constructor.prototype === aaa.prototype
  3. _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
  4. _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__,你们会说,你有完没完

,那我就不分析了,我来推断:

推断:

  1. 任何自定义的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构造出来的

    我们来测试一下ccc

    ccc.__proto__.__proto__.__proto__ === null // true
  2. 继承关系的function fn,假设继承次数为n,

    _fn = new fn();

    那么 _fn.__protot__[3 + n] === null

    _ccc应该是3+2就是5次

    _ccc.__proto__.__proto__.__proto__.__proto__.__proto__ === null // true
  3. 继承关系的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`

  1. __proto__

    因为这些都是Function创建出来的函数,__proto__在函数上时就是表示构造函数的prototype,所以

    .__proto__ === .constrcutor.prototype === Function.prototype
  2. .prototype.__proto__ 这些老骨头不遵循 __proto__ 为构造函数的prototype

    在上面提到过了,Function.prototype.__proto__ === Object.prototype

    类推,这些内置的老骨头的 .prototype.__proto__ === Object.prototype

总结

总结, 特别需要记忆的:

  1. Object.prototype.__proto__ === null
  2. Function.prototype.__proto__ === Object.prototype

    内置Number,Boolen, String,Function, Date, Array, RegExp等一样
  3. Object.__proto__ === Function.prototype === Function.__proto__

    联系2,这些东西都是Function创建出来的
  4. Math, JSON的__ptoto__是 Object.prototype

    typeof 可以看出来这两个是object,而不是Function
  5. function a(){} 这样创建出来,没有继承关系的函数

    a.prototype.__proto__ === Object.prototype
  6. 有继承关系的function看上面的推断
  7. 对象字面量和new Object() 比如, var a ={}, b = new Object(), c = [];

    a.__proto__ === a.constructor.prototype === Object.protype

    a.__proto__.__proto__ === Object.protype.__proto__ === null
  8. 基本数据类型string,number,boolean,比如 var a = '', b=10, c= false,

    b.__proto__ === b.constructor.prototype === Number.prototype

    b.__proto__.__proto__ === Number.prototype.__proto__ === Object.prototype

    b.__proto__.__proto__.__proto__ === Object.prototype.__proto__ === null
  9. null和undefined没有__proto__

最终

  1. 看图
  2. 浏览器输入 xx.__proto__ 或者xx.prototype自己看去

深入__proto__和prototype的区别和联系的更多相关文章

  1. 谈谈__proto__和prototype的区别

    我想javascript中的原型链一直想很多初学javascript的同学感到非常的困惑,今天看了一些文章,结合自己的理解,把原型链这个东西从新来整理一下,如有不对之处,望大家帮忙指出. 首先,我们应 ...

  2. js中__proto__和prototype的区别和关系? 这样好理解多了

    原型的概念 真正理解什么是原型是学习原型理论的关键.很多人在此产生了混淆,没有真正理解,自然后续疑惑更多. 首先,我们明确原型是一个对象,其次,最重要的是, Every function has a ...

  3. js中__proto__和prototype的区别和关系?

    _proto__(隐式原型)与prototype(显式原型)1.是什么 显式原型 explicit prototype property: 每一个函数在创建之后都会拥有一个名为prototype的属性 ...

  4. Javascript深入__proto__和prototype的区别和联系

    有一个一个装逼的同事,写了一段代码 function a(){} a.__proto__.__proto__.__proto__ 然后问我,下面这个玩意a.__proto__.__proto__.__ ...

  5. 理解js中__proto__和prototype的区别和关系

    首先,要明确几个点:1.在JS里,万物皆对象.方法(Function)是对象,方法的原型(Function.prototype)是对象.因此,它们都会具有对象共有的特点.即:对象具有属性__proto ...

  6. [转载]js中__proto__和prototype的区别和关系

          首先,要明确几个点:1.在JS里,万物皆对象.方法(Function)是对象,方法的原型(Function.prototype)是对象.因此,它们都会具有对象共有的特点.即:对象具有属性_ ...

  7. 【JavaScript】__proto__和prototype的区别和联系【整理】

    var person={name:'ninja'}; person.prototype.sayName=function(){ return this.name; } Chrome运行结果: 提示找不 ...

  8. js中__proto__和prototype的区别和关系

          首先,要明确几个点:1.在JS里,万物皆对象.方法(Function)是对象,方法的原型(Function.prototype)是对象.因此,它们都会具有对象共有的特点.即:对象具有属性_ ...

  9. (转)js中__proto__和prototype的区别和关系

    作者:doris链接:https://www.zhihu.com/question/34183746/answer/58155878来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...

随机推荐

  1. eclipse导入Java源码

    eclipse导入Java源码 下载源码包(一般jdk都自带了, 我的没有) src.zip eclipse -> window -> preferences -> JAVA -&g ...

  2. ACM ICPC, JUST Collegiate Programming Contest (2018) Solution

    A:Zero Array 题意:两种操作, 1 p v  将第p个位置的值改成v  2  查询最少的操作数使得所有数都变为0  操作为可以从原序列中选一个非0的数使得所有非0的数减去它,并且所有数不能 ...

  3. Python: 矩阵与线性代数运算

    需要执行矩阵和线性代数运算,比如矩阵乘法.寻找行列式.求解线性方程组等等. 矩阵类似于3.9 小节中数组对象,但是遵循线性代数的计算规则.下面的一个例子展示了矩阵的一些基本特性: >>&g ...

  4. python中小数点后取2位(四舍五入)以及取2位(四舍五不入)

    一.小数点后取2位(四舍五入)的方法方法一:round()函数其实这个方法不推荐大家使用,查询资料发现里面的坑其实很多,python2和python3里面的坑还不太一样,在此简单描述一下python3 ...

  5. MySql如何安装?

    官方网址:https://www.mysql.com/downloads/ Community——>MySqlCommunity Server->GA->64位: GA:正式版: C ...

  6. 《Java入门第二季》第一章 类和对象

    什么是类和对象 如何定义 Java 中的类 如何使用 Java 中的对象 Java中的成员变量和局部变量1.成员变量:在类中定义,描述构成对象的组件. 2.局部变量:在类的方法中,用于临时保存数据. ...

  7. P1174 打砖块

    P1174 打砖块 普通分组背包:50pts 题解说的啥????(大雾) 看了半天 $s[0/1][i][j]$表示第$i$列用$j$发子弹,最后一发是1/否0打在该列上的价值 $f[0/1][i][ ...

  8. 自动化运维工具SaltStack安装配置

    SaltStack是一种全新的基础设置管理方式,部署轻松,在几分钟内可运作起来,扩展性好,很容易管理上万台服务器,速度够快,服务器之间秒级通讯.通过部署SaltStack环境,我们可以在成千上万台服务 ...

  9. linux及安全第五周总结——20135227黄晓妍

    (注意:本文总结备份中有较多我手写笔记的图片,其中重要的部分打出来了.本文对分析system_call对应的汇编代码的工作过程,系统调用处理过程”的理解,以及流程图都写在实验部分.) 实验部分 使用g ...

  10. 20145211黄志远《网络对抗》Exp9 Web安全基础实践

    20145211黄志远<网络对抗>Exp9 Web安全基础实践 基础问题回答 SQL注入攻击原理,如何防御? SQL注入攻击就是利用输入的机会构造自己期望的请求,比如破坏掉用户名或者密码验 ...