前言
很久以前,还比较白的时候呀, 某某同事,show me的下面的code
function A(){} A.__proto__.__proto__.__proto__ 复制代码
然后问我,下面这个玩意A.__proto__.__proto__.__proto__
是啥,然后我一脸懵逼,prototype还知道一点,这个__proto__
,还来三个,是个什么鬼。于是我一直不能放下这个问题,虽然我很懒,很不喜欢费脑子,但是这个坎还是过不去,最近两天研究了大半天,就有了这篇文章。
至于答案, 看本文标题就知道值为 null。
我还很负责的告诉你,下面的值也是null:
这个和前面代码是有区别的,这里用new
进行了实例化。
function A(){} var a = new A(); a.__proto__.__proto__.__proto__ 复制代码
经典之图
先来一张非常经典的图,真的是非常经典,你看懂他,你就懂了整个世界,然后整个世界就等着你去拯救整个世界。
__proto__和prototype
都谁有的问题
typeof === object
(null除外)的有__proto__
typeof === function
的有__proto__
和prototype
null和undefined都没有
__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 // true 复制代码
Function.prototype.__proto__ === Object.prototype
有没有点一切皆对象的设计。
Function.prototype.constructor === Object // false 复制代码
自定义函数,默认情况下,比如 function Person(){}
有下面的规律:
Person.prototype.__proto__ === Object.prototype
Person.constructor === Function
正题
有这几个基本东西,我们就可以来推导了。
先看下面的代码,
js 我们来推到 A.__proto__.__proto__.__proto__
function A(){} var a = new A() 复制代码
A.__proto__
A构造函数是Function
A.constructor === Function
A.__proto__ === Function.prototype
A.__proto__.__proto__
A.__proto__.__proto__ === Function.prototype.__proto__
依据 Function.prototype.__proto__ === Object.prototype
A.__proto__.__proto__ === Function.prototype.__proto__ === Object.prototype
A.__proto__.__proto__.__proto__
A.__proto__.__proto__.__proto__ === Object.prototype.__proto__
依据 Object.prototype.__proto__ === null
A.__proto__.__proto__.__proto__ === null
到此为止,标题部分我们已经推导完毕。
这才哪到哪,继续推导下面的代码
function A(){} var a = new A(); a.__proto__.__proto__.__proto_ 复制代码
还是上面代码,我们接着推导a.__proto__.__proto__.__proto__
a.__proto__
a的构造函数是 A
a.constructor === A
a.__proto__ === a.constructor.prototype
a.__proto__ === A.prototype
a.__proto__.__proto__
a.__proto__.__proto__ === A.prototype.__proto__
根据规则三,再参考图,Foo.prototype.__proto__ === Object.prototype
a.__proto__.__proto__ === A.prototype.__proto__ === Object.protype
a.__proto__.__proto__.__proto__
a.__proto__.__proto__.__proto__ === Object.protype.__proto__
根据规则一 Object.prototype.__proto__ === null
a.__proto__.__proto__.__proto__ === null
正题延伸, 加上继承关系
我们再来看看,带继承关系的
function Parent(){} function Child(){} Child.prototype = new Parent() var child = new Child(); 复制代码
Parent.__proto__.__proto__.__proto__ === null
这个没啥好说的。
Child.prototype.__proto__.__proto__.__proto__
先来看看 Child.prototype.__proto__.__proto__.__proto__
Child.prototype.__proto__
Child.prototype.__proto__ === Child.prototype.constructor.prototype
Child.prototype的原型是 Parent的实例, Child原型的构造函数就是Parent,所以
Child.prototype.__proto__ === Parent.prototype
Child.prototype.__proto__.__proto__
Child.prototype.__proto__.__proto__ === Parent.prototype.__proto__
参考图,Foo.prototype.__proto__ === Object.prototype
Child.prototype.__proto__.__proto__ === Object.prototype
Child.prototype.__proto__.__proto__
Child.prototype.__proto__.__proto__ .__proto__=== Object.prototype.__proto__ === null
child.__proto__.__proto__.__proto__ .__proto__
再来看看child.__proto__.__proto__.__proto__ .__proto__
child.__proto__
child.__proto__ === Child.prototype
child.__proto__.__proto__
child.__proto__.__proto__ === Child.prototype._proto__ === Child.prototype.constructor.prototype === Parent.prototype
child.__proto__.__proto__.__proto__
child.__proto__.__proto__.__proto__ === Parent.prototype.__proto__
参考图Foo.prototype.__proto__ === Object.prototype
child.__proto__.__proto__.__proto__ === Parent.prototype.__proto__ === Object.prototype
child.__proto__.__proto__.__proto__.__proto__
child.__proto__.__proto__.__proto__.__proto__ === Object.prototype.__proto__ === null
正文 再加量
看看如下代码
function Grandpa(){} function Parent(){} Parent.prototype = new Grandpa(); function Child(){} Child.prototype = new Parent() var child = new Child() 复制代码
我们再来分析child的prototype
和__proto__
,你们会说,你有完没完,
那我就不分析了,我来推导公式:
推导公式
- 任何自定义的function,默认情况,三次
.__proto__
必然是null
也就是往上找三代, 包括Function,Object, Error等等
依据 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
Child.__proto__.__proto__.__proto__ === null // true 复制代码
- 继承关系的 function Fn,假设继承次数为 n,
fn = new Fn()
;
那么 fn.__proto__[3 + n] === null
child应该是3+2就是5次
child.__proto__.__proto__.__proto__.__proto__.__proto__ === null // true 复制代码
- 继承关系的function Fn,假设继承次数为n
推导 Fn.prototype.__proto__[3+n-1]
Child应该是 4次__proto__
```js Child.prototype.__proto__.__proto__.__proto__.__proto__ === null // true ``` 复制代码
当然上面关联的关系,就自己慢慢看吧
正文之外, class
下面的代码也是遵守规则,至于为什么,问自己喽。
class Grandpa {} class Parent extends Grandpa{} class Child extends Parent{}; var child = new Child() 复制代码
关于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__ === null
Function.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,而不是Functionfunction A(){}
默认的原型关系如下
A.prototype.__proto__ === Object.prototype
- 有继承关系的function看上面的推断
- 对象字面量和new Object() 比如, var a ={}, b = new Object(), c = [];
a.__proto__ === a.constructor.prototype === Object.protype
a.__proto__.__proto__ === Object.protype.__proto__ === null
两次.__proto__
为null - 基本数据类型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
三次.__proto__
为null - null和undefined没有
__proto__
最终
- 看图
- 浏览器输入
xx.__proto__
或者xx.prototype自己看去