写在前面
这篇博客来源于,有天mentor突然传给我了这张祖传的图片,并且发誓一定要给我讲清楚,然鹅在他的一番激情讲解之后,他自己也被绕懵了...
于是后来我决定整理一下似乎还有点清晰的思路,记录一下我对这张图的理解。作为一个小白,对于js中这些比较复杂的概念的理解还是很有可能出现偏差的,如果哪里出现了各种错误TUT请各位大神不吝赐教!感觉自己写的是真的很绕...啊..惆怅...先上一张图再说
prototype & _proto_ & constructor 之间的关系
这张图乍看起来有些复杂,我们先看图中的一小部分:这部分出现了三种关系指向prototype
,_proto_
,constructor
。
要搞清这三种关系指向之间的关系(拗口...),其实也就是要搞懂,构造函数
、由构造函数new操作创造出的实例对象
、和构造函数的原型对象
之间的关系。
- prototype是
函数
(关系中的构造函数Foo)的属性 - _proto_和constructor都是
对象
的属性 - _proto_是
对象
(关系中的实例对象f1,f2)的属性 - constructor也是
对象
(关系中的原型对象Foo.prototype)的属性
就拿图里面例子来说:
-
f2,f1
是由构造函数Foo()
构造出的实例对象。 -
Foo
是一个构造函数,他的prototype属性则是一个指针,指针指向了Foo的原型对象,Foo.prototype
,之所以要费这么大劲指向一个原型对象呢?就是为了共享原型对象里所包含的属性和方法呀~通过Foo
构造出的f1,f2
就同时拥有了原型对象里的属性和方法。 -
Foo.prototype
在Foo
的prototype
属性指向它之时,它所包含的constructor
属性也指向回了它的构造函数Foo
. - 构造函数new操作出的实例对象和构造函数之间是没有直接的指向关系的,实例对象被new出来的时候,它的_proto_属性直接指向了构造函数的原型对象。
图里还包含了其他这样的"三角关系":
这张图描述的是Object(js中最基本的对象)和它的实例、构造函数之间的关系。
o1,o2
是Object的实例对象,Object()
是Object对象的构造函数。此时~注意红框框标注出的部分,由于Object是js中最基本的对象(兜底对象...),所以Object
的_proto_
指向的是null
函数也是对象!
咦?这组关系就有点奇怪了,我们中出现了一个叛徒!Foo()
这个构造函数为什么也有_proto_
属性?
- 因为在广阔的js世界中~函数也是一个对象~函数也会有
_proto_
属性,并且这个_proto_
属性指向了是函数的原型对象Function.prototype
,而它的构造函数则是大Function()
。即小function
其实是由大Function()
new操作出的实例! - 然鹅不要忘了我们的大Function()同志也是个构造函数呀、也是个函数实例呀、也有_proto_属性,并且同样指向了function们的共同原型
Function.prototype
.(相当的绕...)
原型链
最后再整体看一遍这张图,这些对象之间的原型指向最终连成了一条原型链,指向基础对象Object
-
f1,f2
是对象,它的_proto_
属性指向了Foo.prototype
。而Foo.prototype
也是对象,它的_proto_
属性指向了兜底中的Object.prototype
,形成了一条原型链。 -
function Foo()
是函数也是对象,它的_proto_
属性指向着函数共同的原型Function.prototype
。Function.prototype
是对象,它也有_proto
属性,而这个属性最终也会指向我们的兜底Object.prototype
,这又是另一条原型链。 - 原型链在js中的作用就相当于java中的继承思想,一个实例对象可以继承到它的原型链上的所有原型对象的属性和方法。
参考资料
- 红宝石