javascript学习笔记(二)--继承

原文出处:http://www.blogjava.net/ilovezmh/archive/2007/04/16/111106.html


一、继承的方式
1.对象冒充
function ClassA(sColor) {
    this.color = sColor;
    this.sayColor = function () {
        alert(this.color);
    };
}

function ClassB(sColor, sName) {
    this.newMethod = ClassA;
    this.newMethod(sColor);
    delete this.newMethod;
    
    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };    
}

var objA = new ClassA("red");
var objB = new ClassB("blue", "Nicholas");
objA.sayColor();
objB.sayColor();
objB.sayName();
所有新的属性和新的方法都必须在删除了新方法的代码行后定义。否则,可能会覆盖超类的相关属性和方法。
对象冒充可以支持多继承。
function ClassZ(){
   this.newMethod = ClassX;
   this.newMethod(sColor);
   delete this.newMethod;

   this.newMethod = ClassY;
   this.newMethod(sColor);
   delete this.newMethod;
}
这里存在一个弊端,如果ClassX和ClassY具有相同的属性或方法,ClassY具有高优先级,因为继承的是最后的类。

2.call()方法
call()方法是与经典的对象冒充方法最相似的方法,它的第一个参数用作this的对象,其他参数都直接传递函数自身。
function ClassA(sColor) {
    this.color = sColor;
    this.sayColor = function () {
        alert(this.color);
    };
}

function ClassB(sColor, sName) {
    //this.newMethod = ClassA;
    //this.newMethod(color);
    //delete this.newMethod;
    ClassA.call(this, sColor);

    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}

var objA = new ClassA("red");
var objB = new ClassB("blue", "Nicholas");
objA.sayColor();
objB.sayColor();
objB.sayName();

3.apply()方法
apply()方法有两个参数,用作this的对象和要传递参数的数组。例如:
function ClassA(sColor) {
    this.color = sColor;
    this.sayColor = function () {
        alert(this.color);
    };
}

function ClassB(sColor, sName) {
    //this.newMethod = ClassA;
    //this.newMethod(color);
    //delete this.newMethod;
    ClassA.apply(this, arguments);

    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}

var objA = new ClassA("red");
var objB = new ClassB("blue", "Nicholas");
objA.sayColor();
objB.sayColor();
objB.sayName();

当然,只有超类中的参数顺序与子类中的参数顺序完全一致时才可以传递参数对象。如果不是,就必须创建一个单独的数组,按照正确的顺序放置参数。此外,还可以使用call()方法。

4.原型链
function ClassA() {
}

ClassA.prototype.color = "red";
ClassA.prototype.sayColor = function () {
    alert(this.color);
};

function ClassB() {
}

ClassB.prototype = new ClassA();

ClassB.prototype.name = "";
ClassB.prototype.sayName = function () {
    alert(this.name);
};

var objA = new ClassA();
var objB = new ClassB();
objA.color = "red";
objB.color = "blue";
objB.name = "Nicholas";
objA.sayColor();
objB.sayColor();
objB.sayName();
注意,调用ClassA的构造函数时,没有给它传递参数。这在原型链中是标准做法。要确保构造函数没有任何参数。
原型链的弊端是不支持多重继承。

5.混合方式
与创建对象最好方式相似,用对象冒充继承构造函数的属性,用原型链继承prototype对象的方法。
function ClassA(sColor) {
    this.color = sColor;
}

ClassA.prototype.sayColor = function () {
    alert(this.color);
};

function ClassB(sColor, sName) {
    ClassA.call(this, sColor);
    this.name = sName;
}

ClassB.prototype = new ClassA();

ClassB.prototype.sayName = function () {
    alert(this.name);
};


var objA = new ClassA("red");
var objB = new ClassB("blue", "Nicholas");
objA.sayColor();
objB.sayColor();
objB.sayName();


二、其他继承方式
1.zlnherit库
可以从http://www.nczonline.net/downloads处下载
zInherit库给Object类添加了两个方法,inheritFrom()和instanceOf()
ClassB.prototype.inheritFrom(ClassA);
CalssB.instanceOf(ClassA);

2.xbObjects库
可以从http://archive.bclary.com/xbprojectsdocs/xbobject/处下载
第一步,必须注册类。
_classes.registerClass("Subclass_Name","Superclass_Name");
         这里,子类和超类名都以字符串形式传进来,而不是指向它们的构造函数的指针。这个调用必须放在指定子类的构造构函数前。
第二步,在构造函数内调用defineClass()方法,传给它类名及被Clary称为原型函数的指针,该函数用于初始化对象的所有属性和方法。

_classes.registerClass("ClassA");
function ClassA(color){
   _classes.defineClass("ClassA",prototypeFunction);

   function prototypeFunction(){
      //...
   }
}
第三步,为该类创建init()方法。该方法负责设置该类的所有属性,它必须接受与构造函数相同的参数。作为一种规约,init()方法总是在defineClass()方法后调用。
_classes.registerClass("ClassA");
function ClassA(color){
   _classes.defineClass("ClassA",prototypeFunction);
   this.init(sColor);
   function prototypeFunction(){
     ClassA.prototype.init = function(sColor){
         this.parentMethod("init");
         this.color = sColor;
      }
   }
}
第四步,在原型函数内添加其他类的方法。
_classes.registerClass("ClassA");
function ClassA(color){
   _classes.defineClass("ClassA",prototypeFunction);
   this.init(sColor);
   function prototypeFunction(){
     ClassA.prototype.init = function(sColor){
         this.parentMethod("init");
         this.color = sColor;
      }
      ClassA.prototype.sayColor = function(){
         alert(this.color);
      }
   }
}
然后,即可以以常规方式创建ClassA的实例
var objA = new ClassA("red");
objA.sayColor();      //outputs "res"

posted @ 2011-09-16 10:19  gds111789  阅读(177)  评论(0编辑  收藏  举报