| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2460 人关注过本帖
标题:ECMAScript 3rd阅读笔记之一——js prototype链解惑
只看楼主 加入收藏
渚薰
Rank: 6Rank: 6
等 级:贵宾
威 望:22
帖 子:1132
专家分:0
注 册:2006-8-6
收藏
 问题点数:0 回复次数:5 
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: 4
等 级:贵宾
威 望:11
帖 子:2876
专家分:244
注 册:2007-4-5
收藏
得分:0 
没看懂,那么 prototype到底相当于一个构造函数,还是一个类呢?感觉和c++的构造函数和类有些相似,prototype到底是怎么样的一个机制。个人看法,可能想法乱七八糟,请指教。
2007-11-16 20:22
渚薰
Rank: 6Rank: 6
等 级:贵宾
威 望:22
帖 子:1132
专家分:0
注 册:2006-8-6
收藏
得分:0 
js不是class-based的,是object-based的,prototype机制就是基于对象的继承机制

个人ajax技术专题站: " target="_blank">http://www. 我不会闲你烦,只会闲你不够烦!
2007-11-19 09:51
madpbpl
Rank: 4
等 级:贵宾
威 望:11
帖 子:2876
专家分:244
注 册:2007-4-5
收藏
得分:0 
以下是引用渚薰在2007-11-19 9:51:40的发言:
js不是class-based的,是object-based的,prototype机制就是基于对象的继承机制

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

2007-11-19 14:00
渚薰
Rank: 6Rank: 6
等 级:贵宾
威 望:22
帖 子:1132
专家分:0
注 册:2006-8-6
收藏
得分:0 
js中的继承,也就是通过隐含引用对象的prototype,而不是真正的继承。
就比如我上面的例子,b是个构造器,b有一个prototype属性
c初始化b的一个实例,那么c就隐含引用了b的prototype属性,那么在通过c访问属性和方法,假如c自身没有这个属性或方法(即,没有通过c.xxx去显示赋值声明),那么就会去它隐含引用的prototype属性中去找,即b.prototype,而b.prototype本身也是一个对象,以此类推的去找属性或方法。

个人ajax技术专题站: " target="_blank">http://www. 我不会闲你烦,只会闲你不够烦!
2007-11-20 08:50
madpbpl
Rank: 4
等 级:贵宾
威 望:11
帖 子:2876
专家分:244
注 册:2007-4-5
收藏
得分:0 
非常感谢,理解了,再找些资料看看,消化一下!
2007-11-20 13:04
快速回复:ECMAScript 3rd阅读笔记之一——js prototype链解惑
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.024714 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved