JavaScript 原型链例子讲解

在JavaScript秘密花园(http://bonsaiden.github.io/JavaScript-Garden/zh/#object.prototype)里看到了一个比较经典的原型链的例子,拿出来分享一下。 案例:

<!-- lang: js -->
function Foo() {
this.value = 42;
}
Foo.prototype = {
    method: function() {}
};

function Bar() {}

// 设置Bar的prototype属性为Foo的实例对象
Bar.prototype = new Foo();
Bar.prototype.foo = 'Hello World';

// 修正Bar.prototype.constructor为Bar本身
Bar.prototype.constructor = Bar;

var test = new Bar() // 创建Bar的一个新实例

结果:

<!-- lang: js -->
// 原型链
test [Bar的实例]
    Bar.prototype [Foo的实例] 
        { foo: 'Hello World' }
        Foo.prototype
            {method: ...};
            Object.prototype
                {toString: ... /* etc. */};

分析: 1 Foo&Foo.prototype

<!-- lang: js -->
function Foo() {
this.value = 42;
}

Foo的prototype指向了Foo.prototype,Foo.prototype的constructor指向了Foo。此时Foo.prototype.constructor=Foo。另外,Foo.constructor指向了Function。后面都用图来表示,更清晰。

在此输入图片描述

2 Foo.prototype

<!-- lang: js -->
Foo.prototype = {
method: function() {}
};

由于Foo.prototype通过{}创建了一个新的对象,这个对象继承了Object.prototype。所以,Foo.prototype.constructor指向了Object。

在此输入图片描述

3 Bar&Bar.prototype

<!-- lang: js -->
function Bar() {}

Bar和第一步的Foo很像,什么都不说了。 在此输入图片描述

4 Bar.prototype&Foo.prototype

<!-- lang: js -->
// 设置Bar的prototype属性为Foo的实例对象
Bar.prototype = new Foo(); 
Bar.prototype.foo = 'Hello World';

Bar.prototype创建了Foo的对象实例,根据原型链回溯原理,Bar.prototype回溯到Foo.prototype,又因为Foo.prototype的constructor指向Object,所以Bar.prototype的constructor也指向了Object,Bar.prototype拥有了value属性和method属性。不同的是,Foo.value改变了之后,Bar.prototype.value不会随之改变。而Foo.prototype.method改变了之后,Bar.prototype.method会随之改变。也就是说,Foo.prototype中的属性会共享到Bar.prototype中。 如果执行的是Bar.prototype=Foo,就不会执行Foo.prototype,而是指向Foo,原型链会回溯到Function.prototype。这样的话,method就不会出现在Bar.prototype上。

在此输入图片描述

5 Bar.prototype

<!-- lang: js -->
// 修正Bar.prototype.constructor为Bar本身
Bar.prototype.constructor = Bar;

这里什么都不说了。在下面一步中详解。 在此输入图片描述

6 test

<!-- lang: js -->
 var test = new Bar() // 创建Bar的一个新实例

不得不说,高潮来了。 如果没有第5步的修正,那么根据回溯原理,test.constructor是指向Object的,为了让test.constructor指向Bar,所以执行了第5步。那么意义何在?看了http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html之后,豁然开朗。理由是为了避免继承链的紊乱,所以要强势回归。 test对象继承了Bar.prototype,而Bar.prototype又继承了Foo.prototype,所以可以访问method。同时,也可以访问Foo的实例属性value。因为是Bar.prototype创建了Foo的实例,所以new Bar()不会创建新的Foo实例,而是重复使用Bar.prototype创建的那个Foo实例。所有的Bar实例都会共享Bar.prototype.value属性。

转载于:https://my.oschina.net/greenqingqings/blog/157594

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值