没有眼泪
Don't Cry!
posts - 13,comments - 44,trackbacks - 0
        众所周知,javascript中的继承是通过原型对象(prototype)来实现的.原型对象是由函数的构造函数创建,它所拥有的属性能被所有对象共享.初始时原型对象指向一个Object对象,并且定义了一个constructor属性,该属性指向定义该原型对象的构造函数本身,上述过程可以理解为以下代码:
function BaseClass() {
    document.write('This is BaseClass.');
}
BaseClass.prototype 
= new Object();
BaseClass.prototype.constructor 
= BaseClass;
因为原型对象的所有属性能被构造函数创建对象共享,所以创建的对象可以访问这里的constructor属性:
var c = new BaseClass();
document.write(c.constructor 
== BaseClass); //true
c.constructor(); //调用BaseClass函数,输出This is BaseClass.
由于对象本身也可以自定义属性,所以在读取对象属性时js先检查该对象是否定义了该属性,如果已经定义了则使用该属性,如果没有定义则再从其原型对象中读取该属性,所以如果对象自定义的属性和其原型中的属性存在重名则自定义属性"隐藏"了其原型对象中的同名属性.例:
c.constructor = function() {
    document.write('This is c');
}
c.constructor(); 
//This is c
加入上述代码之后再次调用c.constructor(),则会打印出"This is c".这是因为c已自定义constructor属性"隐藏"了其原型对象中的constructor属性.当然js保证了读写的不对称性,也就是说读取一个对象的属性时有可能要从其原型对象中去读取,但写一个对象的属性时却从不涉及其原型对象,无论在一个对象加入或修改多少属性这都不影响其原型对象中属性的本来面目.比如这里c自定义了constructor属性,但这一行为并不影响其原型对象中constructor指向其构造函数这一事实,如果再创建一个对象且不自定义constructor属性,再调用constructor则依然调用对象的构造函数,例:
var b = new BaseClass();
b.constructor(); 
//调用BaseClass函数,输出This is BaseClass.

很容易理解js为什么这样做,因为一个对象的行为不能影响到其他对象,否则将会造成混乱.
        理解上述规则之后让我们看看js中是如何通过原型对象实现继承的.当我们创建一个对象时,可以把该对象看成是由2部分组成的,一部分存储了该对象自己定义的属性(称为A部分),而另一个部分则存储了其构造函数所定义的原型对象引用(称为B部分),例如这里的BaseClass.prototype.当读取对象的属性时可以分为以下2步:
1.js先检查该对象引用所指向的内存区域的A部分是否存在该属性,如果存在则读出.
2.如果没有则再从B部分存储的引用(BaseClass.prototype)所指向的内存区域中读取该属性.

从步骤2开始这就是个不断往上寻找的过程,因为BaseClass.prototype所指向的内存区域也会分为A和B两个部分,如果再A部分也不存在该属性,则又会从其B部分所指向的内存区域去寻找该属性,而该内存区域也有A和B两个部分,如果A部分仍然不存在,则还要从B部分所指向的内存区域去寻找该属性,直到达到最顶层的Object类.所以在无形当中就形成了一条链,也就是我们常说的原型链.如果理解了这个过程我想也就能了解原型对象了.下面简单分析下b.constructor();的调用过程便于加深理解.
1.js会在b所指向的内存区域A部分读取constructor属性.
2.当发现没有该属性后再从其类的构造函数原型对象引用所指向的内存区域读取该属性.因为原型对象引用初始时指向一Object对象内存区域(BaseClass.prototype = new Object();)
3.再从此Object对象的A部分寻找constructor属性.
4.没有找到该属性则从其类的原型对象即Object.prototype中去寻找constructor.
5.如果找到该属性则调用.
6.否则,到达链的顶端,返回.
到此能很清楚的知道js中是如何实现继承的,如果我们自定义的类不想继承自Object,则可以修改其prototype的指向,可以让其指向任意一个类,这样也就实现了继承自定义类,但js中所有的类都继承自Object类,所以原型链的关系仍然存在.

posted on 2008-05-09 16:43 zhangchao 阅读(1018) 评论(3)  编辑  收藏 所属分类: javascript

FeedBack:
# re: 我所理解的原型对象[未登录]
2008-12-07 19:10 | simon
受教  回复  更多评论
  
# re: 我所理解的原型对象
2010-06-08 12:41 | #
非常不错  回复  更多评论
  
# re: 我所理解的原型对象
2013-03-12 15:25 | liger 博客园
非常的好,情不自禁的转了  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: