一文教你深入浅出__proto__和prototype的区别和联系

59 篇文章 6 订阅
59 篇文章 1 订阅

前话

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

1.  `function a(){}`

2.  `a.__proto__.__proto__.__proto__`

然后问我,下面这个玩意a.proto.proto.proto是啥,然后我一脸懵逼,prototype还知道一点,这个proto,还来三个,是个什么鬼。于是我一直不能放下这个问题,虽然我很懒,很不喜欢费脑子,但是这个坎还是过不去,最近两天研究了大半天,就有了这篇文章。

我先说出答案, 上面的值为 null。我还很负责的告诉你,下面的_a.proto.proto.proto也是null


1.  `function a(){}var _a = new a();`

2.  `_a.__proto__.__proto__.__proto__`

先来一张非常经典的图,真的是非常经典,你看懂他,你就懂了整个世界,然后整个世界就等着你去拯救整个世界。)

正文之前, proto_和prototype

都谁有的问题

typeof === object的有proto , null和undefined都没有 typeof === function的有proto和prototype

proto 是什么?

proto 一般情况指向的是该对象的构造函数的prototype,一般情况,因为还有很二般的情况。先来看个简单的例子, 下面的输出是true


1.  `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.protoObject.constructor.prototype === Function.prototype // trueFunction.constructor === Function// true

Function.prototype.proto === Object.prototype 这个就是这样的设计, Function.prototype.constructor === Object // false

自定义函数,没有修改默认原型的情况下,比如 function Person(){}, Person.prototype.proto === Object.prototype Person.constructor === Function 对比3一看,Function和构造函数是Function的Person,他们prototype.proto的指向是一样的。

进入正题

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

先看下面的代码,


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

2.  `function aaa(){} var _aaa = new aaa()`


1.  `aaa.__proto__`

2.  `aaa构造函数是Function`

3.  `aaa.constructor === Function`

4.  `aaa.__proto__ === Function.prototype`

1.  `aaa.__proto__.__proto__`

2.  `aaa.__proto__.__proto__ === Function.prototype.__proto__`

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

4.  `aaa.__proto__.__proto__ === Function.prototype.__proto__ === Object.prototype`

1.  `aaa.__proto__.__proto__.__proto__`

2.  `aaa.__proto__.__proto__.__proto__ === Object.prototype.__proto__`

3.  `依据 Object.prototype.__proto__ === null`

4.  `aaa.__proto__.__proto__.__proto__ === null`

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


1.  `_aaa.__proto__`

2.  `_aaa的构造函数是 aaa`

3.  `_aaa.constructor === aaa`

4.  `_aaa.__proto__ === _aaa.constructor.prototype`

5.  `_aaa.__proto__ === aaa.prototype`


1.  `_aaa.__proto__.__proto__`

2.  `_aaa.__proto__.__proto__ === aaa.prototype.__proto__`

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

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

1.  `_aaa.__proto__.__proto__.__proto__`

2.  `_aaa.__proto__.__proto__.__proto__ === Object.protype.__proto__`

3.  `依据 Object.prototype.__proto__ === null`

4.  `_aaa.__proto__.__proto__ === null`

正文延伸, 加上继承关系

我们再来看看,带继承关系的


1.  `function aaa(){}function bbb(){}`

2.  `bbb.prototype = new aaa()var _bbb = new bbb();`

3.  `bbb.__proto__.__proto__.__proto__ === null`

这个没啥好说, 关键来看看 bbb.prototype.proto.proto.proto1.


1.  `bbb.prototype.__proto__`

2.  `bbb.prototype.__proto__ === bbb.prototype.constructor.prototype`

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

4.  `bbb.prototype.__proto__ === aaa.prototype`


1.  `bbb.prototype.__proto__.__proto__`

2.  `bbb.prototype.__proto__.__proto__ === aaa.prototype.__proto__`

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

4.  `bbb.prototype.__proto__.__proto__ === Object.prototype`


1.  `bbb.prototype.__proto__.__proto__`

2.  `bbb.prototype.__proto__.__proto__ .__proto__=== Object.prototype.__proto__ === null`

再来看看_bbb.proto.proto.proto .proto


1.  `1._bbb.__proto__`

2.  `_bbb.__proto__ === bbb.prototype`


1.  `2._bbb.proto.proto`

2.  `_bbb.__proto__.__proto__ === bbb.prototype._proto__ === bbb.prototype.constructor.prototype === aaa.prototype`


1.  `3._bbb.proto.proto.proto`

2.  `_bbb.__proto__.__proto__.__proto__ === aaa.prototype.__proto__`

3.  `参考图Foo.prototype.__proto__ === Object.prototype`

4.  `_bbb.__proto__.__proto__.__proto__ === aaa.prototype.__proto__ === Object.prototype`


1.  `4._bbb.__proto__.__proto__.__proto__.__proto__`

2.  `_bbb.__proto__.__proto__.__proto__.__proto__ === Object.prototype.__proto__ === null`

正文 再加量

看看如下代码

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

2.  `function bbb(){}`

3.  `bbb.prototype = new aaa();`

4.  `var _bbb = new bbb();`

5.  `function ccc(){}`

6.  `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构造出来的

我们来测试一下ccc


1.  `js ccc.__proto__.__proto__.__proto__ ===  null  // true`

继承关系的function fn,假设继承次数为n,
1.  `_fn = new fn();`

那么


1.  `_fn.__protot__[3+ n] === null`

_ccc应该是3+2就是5次


1.  `js _ccc.__proto__.__proto__.__proto__.__proto__.__proto__ === null// true`

继承关系的function fn,假设继承次数为n

推到 fn.prototype.proto[3+n-1] ccc应该是 4次protojs ccc.prototype.proto.proto.proto.proto === null // true 当然上面关联的关系,就自己慢慢看吧

正文之外, class

下面的代码也是遵守规则,至于为什么,问自己喽


1.  `class aaa {}`

2.  `class bbb extends aaa{}`

3.  `class ccc extends bbb{};`

4.  `var _ccc =  new ccc()`

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()

比如,

1.  `var a ={}, b = newObject(), c = [];`

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

3.  `a.__proto__.__proto__ === Object.protype.__proto__ === null`

4.  `8.基本数据类型string,number,boolean,比如 var a = '', b=10, c= false,`

5.  `b.__proto__ === b.constructor.prototype === Number.prototype`

6.  `b.__proto__.__proto__ === Number.prototype.__proto__ === Object.prototype`

7.  `b.__proto__.__proto__.__proto__ === Object.prototype.__proto__ === null`

8.  `9.null和undefined没有__proto__`

最终

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值