ECMAScript 3rd阅读笔记之一——js prototype链解惑
<FONT size=2> 众所周知,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。</FONT><P>
<P><FONT size=2>为了形象点,我们可以把prototype chain用最形象的图来表示,它就是一条链子:<br> c(=new b())<br> |<br> |—-p=2 <br> |<br> b.prototype<br> |<br> |——–p=1 <br> |<br> …………<br>相应代码如下:</FONT></P>
<P>
<DIV class=dp-highlighter>
<DIV class=bar></DIV>
<OL>
<LI class=alt>var b=function() { </LI>
<LI class="">} </LI>
<LI class=alt>b.prototype.p=1; </LI>
<LI class=""> </LI>
<LI class=alt>var c=new b; </LI>
<LI class="">c.p=2; </LI></OL></DIV><br><FONT size=2> b是一个构造器,c通过new初始化一个b的实例。然后,c在“修改”p的值为2。需要注意的是,我在修改这个词上加了引号,这是有原因的。<br> 先来看看,如果运行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链走下去为止。<br>所以,事实,当c初始化为b的实例时,访问c.p,并不是真正访问c对象中的p属性,而是c在prototype链上的p属性。于是,假如在初始化后,用语句c.p=3来“修改”p的值,其实不是“修改”,而是覆盖。即用c对象自己的p属性覆盖了在prototype链上的p属性。而之后是仍旧可以找回prototype链上的p属性的。关于此方法请参见我的另一篇文章<a href="http://www.ajaxgo.org/press/?p=14" target="_blank" >《找回被覆盖掉的原型属性》</A></FONT><br><FONT size=2>诚然,prototype链确实很晦涩,对初学者也难以理解。对于final user,大可以按照习惯的“继承”思路来看待他们。而对于使用js来进行二次开发的developer,却必须搞清楚令人即爱又恨的prototype chain。<br> 在此后的文章中,将进一步讨论prototype链的问题,同时将再引入另一个奇怪的属性__proto__。它是对象的隐含属性,它的存在,就更加让人匪夷所思了。</FONT>
[align=right][color=#000066][此贴子已经被作者于2007-11-16 18:19:28编辑过][/color][/align]
没看懂,那么 prototype到底相当于一个构造函数,还是一个类呢?感觉和c++的构造函数和类有些相似,prototype到底是怎么样的一个机制。个人看法,可能想法乱七八糟,请指教。 js不是class-based的,是object-based的,prototype机制就是基于对象的继承机制 <DIV class=quote><B>以下是引用<U>渚薰</U>在2007-11-19 9:51:40的发言:</B><BR>js不是class-based的,是object-based的,prototype机制就是基于对象的继承机制</DIV>
<P>这个意思是不是说js不是基于类的,而是基于对象的。就是对对象的函数和函数接口可以继承,类似c++的继承。<BR>ps:个人对c++的继承不怎么了解,知道有这么回事。</P> js中的继承,也就是通过隐含引用对象的prototype,而不是真正的继承。<BR>就比如我上面的例子,b是个构造器,b有一个prototype属性<BR>c初始化b的一个实例,那么c就隐含引用了b的prototype属性,那么在通过c访问属性和方法,假如c自身没有这个属性或方法(即,没有通过c.xxx去显示赋值声明),那么就会去它隐含引用的prototype属性中去找,即b.prototype,而b.prototype本身也是一个对象,以此类推的去找属性或方法。 非常感谢,理解了,再找些资料看看,消化一下!
页:
[1]
