| 编程中国 | 业界新闻 | 技术文章 | 视频教程 | 下载频道 | 程序源码 | 个人空间 | 编程论坛
全能ASP/PHP/ASP.NET主机,支持月付专业 MSSQL 数据库空间,支持月付专业 MySQL 数据库空间,支持月付赛孚耐:软件保护加密专家
身份认证令牌USB KEY   
共有 677 人关注过本帖
标题:ECMAScript 3rd阅读笔记之一——js prototype链解惑
收藏  订阅  推荐  打印 
渚薰
Rank: 12Rank: 12Rank: 12
等级:贵宾
威望:22
帖子:1132
积分:12338
注册:2006-8-6
ECMAScript 3rd阅读笔记之一——js prototype链解惑

众所周知,js不是class-based的,而是object-based。在ecma-262中,开篇对js的继承机制做了简单的描述(见 ecma-262 4.2.1)。其中提到,js中的对象搜索属性的一个链。首先,对象搜索自己定义的属性(即用obj.property的形式直接赋值的属性),如果不存在,则在对象隐含的prototype引用去找,而这个隐含的prototype引用即是其构造函数的prototype属性。这里要注意的是,构造函数的prototype属性仍旧是一个对象。所以,仍旧按照上面的描述规则来进行属性搜索,直到最终找到这个属性或者不存在隐含的prototype引用(即再也不能通过链属性了)为止。这就是ecma-262中的prototype chain。

为了形象点,我们可以把prototype chain用最形象的图来表示,它就是一条链子:
c(=new b())
|
|—-p=2
|
b.prototype
|
|——–p=1
|
…………
相应代码如下:

  1. var b=function() {
  2. }
  3. b.prototype.p=1;
  4. var c=new b;
  5. c.p=2;

b是一个构造器,c通过new初始化一个b的实例。然后,c在“修改”p的值为2。需要注意的是,我在修改这个词上加了引号,这是有原因的。
先来看看,如果运行alert(c.p),好无疑问,值是2。那么,假如去掉代码的第6行即c.p=2,此时,在c对象的属性中找不到p,就去找c隐含的prototype引用,即b.prototype。于是找到了b.prototype.p=1,所以输出就是1。又假如去掉代码的第3行即b.prototype.p=1,那么找不到p这个属性,又会去找b.prototype隐含的prototype引用(例如有b.prototype=new a(),而a.prototype.p=0),以此类推。最终等到找到p或者无法再沿隐含的prototype链走下去为止。
所以,事实,当c初始化为b的实例时,访问c.p,并不是真正访问c对象中的p属性,而是c在prototype链上的p属性。于是,假如在初始化后,用语句c.p=3来“修改”p的值,其实不是“修改”,而是覆盖。即用c对象自己的p属性覆盖了在prototype链上的p属性。而之后是仍旧可以找回prototype链上的p属性的。关于此方法请参见我的另一篇文章《找回被覆盖掉的原型属性》

诚然,prototype链确实很晦涩,对初学者也难以理解。对于final user,大可以按照习惯的“继承”思路来看待他们。而对于使用js来进行二次开发的developer,却必须搞清楚令人即爱又恨的prototype chain。
在此后的文章中,将进一步讨论prototype链的问题,同时将再引入另一个奇怪的属性__proto__。它是对象的隐含属性,它的存在,就更加让人匪夷所思了。

[此贴子已经被作者于2007-11-16 18:19:28编辑过]

搜索更多相关主题的帖子: prototype  ECMAScript  笔记  属性  解惑  
2007-11-16 17:48
madpbpl
Rank: 6Rank: 6
等级:金牌会员
威望:7
帖子:2560
积分:27775
注册:2007-4-5

没看懂,那么 prototype到底相当于一个构造函数,还是一个类呢?感觉和c++的构造函数和类有些相似,prototype到底是怎么样的一个机制。个人看法,可能想法乱七八糟,请指教。
2007-11-16 20:22
渚薰
Rank: 12Rank: 12Rank: 12
等级:贵宾
威望:22
帖子:1132
积分:12338
注册:2006-8-6

js不是class-based的,是object-based的,prototype机制就是基于对象的继承机制

个人ajax技术专题站: http://www.ajaxgo.org 我不会闲你烦,只会闲你不够烦!
2007-11-19 09:51
madpbpl
Rank: 6Rank: 6
等级:金牌会员
威望:7
帖子:2560
积分:27775
注册:2007-4-5

以下是引用渚薰在2007-11-19 9:51:40的发言:
js不是class-based的,是object-based的,prototype机制就是基于对象的继承机制

这个意思是不是说js不是基于类的,而是基于对象的。就是对对象的函数和函数接口可以继承,类似c++的继承。
ps:个人对c++的继承不怎么了解,知道有这么回事。

2007-11-19 14:00
渚薰
Rank: 12Rank: 12Rank: 12
等级:贵宾
威望:22
帖子:1132
积分:12338
注册:2006-8-6

js中的继承,也就是通过隐含引用对象的prototype,而不是真正的继承。
就比如我上面的例子,b是个构造器,b有一个prototype属性
c初始化b的一个实例,那么c就隐含引用了b的prototype属性,那么在通过c访问属性和方法,假如c自身没有这个属性或方法(即,没有通过c.xxx去显示赋值声明),那么就会去它隐含引用的prototype属性中去找,即b.prototype,而b.prototype本身也是一个对象,以此类推的去找属性或方法。

个人ajax技术专题站: http://www.ajaxgo.org 我不会闲你烦,只会闲你不够烦!
2007-11-20 08:50
madpbpl
Rank: 6Rank: 6
等级:金牌会员
威望:7
帖子:2560
积分:27775
注册:2007-4-5

非常感谢,理解了,再找些资料看看,消化一下!
2007-11-20 13:04
关于我们 | 广告合作 | 编程中国 | 清除Cookies | Archiver | WAP | TOP

编程中国 版权所有,并保留所有权利。鲁ICP备08000592号
Powered by Discuz, Processed in 0.152289 second(s), 9 queries.
Copyright©2004-2008, BCCN.NET, All Rights Reserved