js继承2:图解原型链中prototype和constructor的关系

一:问题的起因是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//1 声明对象
function F() {
};
//2 重写原型
F.prototype = {
_name: 'ruantao.duapp.com',
getName: function() {
return this._name;
}
};
//3 出现问题, f.constructor === F为false
var f = new F();
console.log(f.constructor === F); //输出 false
//实际上 f.constructor 指向function Object()

问题在于:
F.prototype被赋值为字面量对象{}, 而{}相当于是new Object().
所以解决问题的方法如下:
所以说, 想要修正F的prototype原型链, 需要在F.prototype的字面量中, 赋值

1
2
F.prototype = {
constructor: F// !!!注意==> 讨论的问题里并未修正F的prototype原型链, 实际上应该修改指向

二: 到这其实目标已经完成了

但是上述代码除了修正了F的原型链, 还意外的说明实例f.constructor指向了Object
那么第一个问题来了:
1.Object的constructor指向哪呢?
Object.constructor//function Function() { [native code] }
//指向”Function”
//其实js内置对象Array, Sting, Number, Function的constructor都指向”Function”

如果说类(function F())中有有prototype, 对象(var f = new F())中有constructor,
那么第二个问题来了:
2.Object有prototype么? Object.prototype里有什么呢?
Object.prototype//Object {}
//空的什么都没有, 这也佐证了F.prototype被赋值为字面量对象{}后, constructor是错误的

第三个问题更有意思:
3.Object.prototype.constructor是什么呢? (也就是说最开始错误的指向哪了呢)
Object.prototype.constructor//function Object() { [native code] }

顺这个思路 第四第五第六第n个问题如下:
Object.prototype.constructor.prototype是什么?
Object.prototype.constructor.prototype.constructor是什么?
… …
Object.constructor.constructor是什么呢?
… …
通过答案其实发现prototype和constructor是循环引用的

三:先来说Object对象的原型链

Object对象的原型链比较特殊:画个草图说明一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 博文作者:ruantao1989{@}gmail.com
* 引自博客:ruantao.duapp.com/blog
*/
//左侧是各个对象的prototype, 中间是对象 , 右侧是constructor的指向
+--------+
| |
v |
+-----------------------+ |
| 1.Function对象 | |
| | |
| Function.constructor|---+
function Empty()<-------| Function.prototype |
+-----------------------+
^
|
+-------------+
|
+-----------------------+ |
| 1.Object对象 | |
| | |
| Object.constructor |---------+
Object{}实例,这就到头了<----| Object.prototype |
+-----------------------+

从上图能看出prototype和constructor是怎么循环引用的, 下面来说最开始碰到的问题

四:prototype和constructor是怎么循环引用的呢

1:先说是不经过修正的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
+--------+
| |
v |
+-----------------------+ |
| 1.Function对象 | |
| | |
| Function.constructor|---+
function Empty()<-------| Function.prototype |
+-----------------------+
^
|
+---------------+
|
+-----------------------+ |
| 2.对象:function F() | |
| | |
| F.constructor |-----------+ //此处如果不经过constructor的修正,则指向Object
Object {} <-------| F.prototype |
+-----------------------+
^
|
+-------------------+
|
+-----------------------+ |
| 3.实例: f = new F() | |
| | |
| f.constructor |---------------+
undefined <---| f.prototype |
+-----------------------+

2:是经过修正的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
+----------------+
| |
v |
+-----------------------+ |
| 1.对象:function F() | |
| | |
| F.constructor |-----------+ 修正构造的指针F.prototype={ constructor: F,
F.prototype = { <-------| F.prototype |
constructor: F, +-----------------------+
_name: 'ruantao.duapp.com', ^
getName: function() { |
} +-------------------+
} |
+-----------------------+ |
| 2.实例: f = new F() | |
| | |
| f.constructor |---------------+
undefined <-------| f.prototype |
+-----------------------+

这样画完就清晰多了