javascript继承学习系列之二:原型链(Prototype Chaining)

    原型链是采用的最主要的继承方式,它的思路是这样的:每一个类(构造器,js中的function)都有一个原型属性(prototype)指向原型对象,原型对象有一个构造器属性(constructor),它又指回到function,是个循环引用。类的每个实例,也有个原型属性(代码无法访问的, 叫做__proto__),它跟构造器原型指向的是同一个对象,即同一个类的所有实例共用一个原型对象。要实现两个类型的继承,就是将一个类型的原型指向另一个类型的实例,而不在指向原来的默认的原型对象。这样就形成了原型链。
    子类可以通过原型链获得超类的所有属性和方法。从而实现了继承。基本的js代码如下:
//supper class
function BaseClass()
{
     this.baseName="BaseClass";
}
BaseClass.prototype.getBaseClassName = function(){return this.baseName;}
//child class
function ChildClass
{
     this.childName="ChildClass";
}
//make prototype chaining, inherit
ChildClass.prototype = new BaseClass();

ChildClass.prototype.getChildClassName = function(){return this.childName;}

var instance = new ChildClass();
alert(instance.getBaseClassName ());//BaseClass
      ChildClass(及它的实例)的prototype(__proto__)属性不再指向默认的prototype对象,而是BaseClass的 实例,这个实例也有个属性(__proto__),它指向的是BaseClass的原型对象。在ChildClass的实例instance上查找 baseName属性的过程是这样的:首先,在实例instance自身上找baseName属性,没有找到,则在它的原型对象(__proto__属 性,此时是BaseClass的实例,不在是默认的原型对象)上查找,并找到baseName属性,返回它的值;而getBaseClassName() 方法的查找,首先是在instance自身上,但并没找到,然后进入的它的原型对象(__proto__属性,此时是BaseClass的实例,不在是默 认的原型对象)上,依然没找到,则进入这个BaseClass的实例的原型对象(__proto__属性,默认的原型对象)上找,终于找到,则返回这个方 法的执行结果。
    像文中强调的那样,类型的原型对象是其所有实例所共有的,这就造成了这样一个问题:原型对象(父类实例)的属性及方法的改变将影响到所有实例,无论是已经创建的还是即将创建的。分析以下代码:
function BaseClass()
{
     this.colors = ["red","blue"];
}
function ChildClass()
{
}
ChildClass.prototype = new BaseClass();

var instance1 = new ChildClass();

//在此实例上对从父类继承过的属性值进行了修改。
var instance2 = new ChildClass();
instance2.colors.push("green");

var instance3 = new ChildClass();

///查看各个实例的colors属性值
alert(instance1.colors);//red,blue,green
alert(instance2.colors);//red,blue,green
alert(instance3.colors);//red,blue,green

可见对于任一个实例来讲,如果修改了它继承的属性值,则将影响到其他任何时候创建的实例。
    另外,如果继承的层次过多,则对最顶层父类中的属性、方法的调用效率最低(推测,没有证实)。
posted @ 2011-07-06 13:27  沈沈  阅读(292)  评论(0编辑  收藏  举报