zoukankan      html  css  js  c++  java
  • 深入__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
    

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

    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自己看去
  • 相关阅读:
    swift 学习线路
    常用linux命令
    位运算常用技巧
    我的算法练习
    mac 电脑配置cordova
    swift 2中关键字和解释整理
    C# 类
    C# 循环语句 for循环(嵌套 while 穷举 迭代)
    C# 循环语句 for循环
    C# 分支语句
  • 原文地址:https://www.cnblogs.com/cloud-/p/9152761.html
Copyright © 2011-2022 走看看