原型和原型链——汤姆大叔

 1 function Foo() {
 2     this.value = 42;
 3 }
 4 Foo.prototype = {
 5     method: function() {}
 6 };
 7 
 8 function Bar() {}
 9 
10 // 设置Bar的prototype属性为Foo的实例对象
11 Bar.prototype = new Foo();
12 Bar.prototype.foo = 'Hello World';
13 
14 // 修正Bar.prototype.constructor为Bar本身
15 Bar.prototype.constructor = Bar;
16 
17 var test = new Bar() // 创建Bar的一个新实例
18 
19 // 原型链
20 test [Bar的实例]
21     Bar.prototype [Foo的实例] 
22         { foo: 'Hello World' }
23         Foo.prototype
24             {method: ...};
25             Object.prototype
26                 {toString: ... /* etc. */};

一开始,Bar是一个非常简单的函数。

之后:

创建一个Foo函数的实例;

为Bar指定原型;

在其原型上定义一个属性;

使得原型对象的constructor属性指向Bar;

到此为止,Bar由最开始的那个简单的函数变成了:

一:原型对象发生改变,原始Bar本来就有原型对象,现在又为它指定了另一个对象而已。

二:这个充当Bar原型的东东,本身是Foo的实例,现在它发生了改变,一来多了个foo属性,二来它的constructor属性指向了Bar。

现在的Bar作为构造函数,创建了test实例。

先给Bar的原型对象起个名字吧,叫bp。

test作为一个对象,拥有_proto_属性,此属性的指向和构造函数Bar的prototype属性的指向是一模一样的。

而“万夫所指”的那个被叫做原型对象的东东,已经有名字啦,就是bp。

回到bp

bp是构造函数Foo的一个实例。

那么bp是什么?

一:bp是Foo的实例

二:bp中的_proto_属性,和构造函数Foo中的prototype属性的指向一样,是属于Foo的原型对象,名叫fp

到此为止,一切都明了。

Foo的原型对象是fp,

Bar的原型对象是bp,

test的原型对象,就是Bar的原型对象bp。

bp是一个活生生的对象,它的原型对象就是fp。

故而:

test的原型对象是bp

bp的原型对象是fp。

正好应了阮一峰老师说的那样:

每一个对象都有自己的原型,

每一个原型都是对象,也拥有自己的原型。

构造函数的各个实例,共享构造函数原型对象。

定义一次,用到多次?

原文地址:https://www.cnblogs.com/flyover/p/14512566.html