javaScript (二)--类的继承

来源:互联网 发布:古方生发液骗局知乎 编辑:程序博客网 时间:2024/06/06 01:01

//---------------《-》、《继承的基本写法》-----------------------
/* 《-》、《继承的基本原理》
* 对象冒充
*   this 指向的所属的对象。这个原理是把 ClassA 作为常规函数来建立继承机制,而不是作为构造函数。如下使用构造函数 ClassB 可以实现继承机制:
*/
function ClassA(sColor) {
    this.color = sColor;
    this.sayColor = function () {
        alert(this.color);
    };
}
function ClassB(sColor) {
    this.newMethod = ClassA;
    this.newMethod(sColor);//即ClassB对象 调用ClassA对象,这时ClassA里面的this 指向ClassB 对象。 从而达到继承的目的。
    delete this.newMethod;
}
/*
* 在这段代码中,为 ClassA 赋予了方法 newMethod(请记住,函数名只是指向它的指针)。然后调用该方法,传递给它的是 ClassB 构造函数的参数 sColor。
* 最后一行代码删除了对 ClassA 的引用,这样以后就不能再调用它。
*/
function ClassZ() {
    this.newMethod = ClassX;
    this.newMethod();
    delete this.newMethod;

    this.newMethod = ClassY;
    this.newMethod();
    delete this.newMethod;
}
//所以可以多重基础

//---------------《二》、call() 方法-----------------------
/*
 * call() 方法是与经典的对象冒充方法最相似的方法。它的第一个参数用作 this 的对象。其他参数都直接传递给函数自身。例如:
 */
function ClassB(sColor, sName) {
    //this.newMethod = ClassA;
    //this.newMethod(color);
    //delete this.newMethod;
    ClassA.call(this, sColor);//我们需要让 ClassA 中的关键字 this 等于新创建的 ClassB 对象,因此 this 是第一个参数。第二个参数 sColor 对两个类来说都是唯一的参数(可以多个)。

    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}
//缺点 因为是对象冒充,所以只能继承 父类中用 this 定义的属性和方法,二对于prototype 定义的不能继承
function ClassA(sColor) {
    this.color = sColor;
 
 if (typeof ClassA._initialized == "undefined") {
  ClassA.prototype.sayColor = function () {
   alert(this.color);
  };
 ClassA._initialized = true;
  }
}
function ClassB(sColor, sName) {
    ClassA.call(this, sColor);// 只能继承 ClassA 里面用this定义的属性和方法

    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}
var testObj=new ClassB('blue','testObk');
testObj.sayColor();//error:testObj.sayColor is not a function
testObj.sayName();

//---------------《二》、apply() 方法-----------------------
/*这个例子与前面的例子相同,只是现在调用的是 apply() 方法。调用 apply() 方法时,第一个参数仍是 obj,说明应该赋予 sayColor() 函数中的 this 关键字值是 obj。
* 第二个参数是由两个字符串构成的数组,与 sayColor() 函数中的参数 sPrefix 和 sSuffix 匹配,
* 最后生成的消息仍是 "The color is blue, a very nice color indeed.",将被显示出来。
*/
function ClassB(sColor, sName) {
    //this.newMethod = ClassA;
    //this.newMethod(color);
    //delete this.newMethod;
    ClassA.apply(this, new Array(sColor));

    this.name = sName;
    this.sayName = function () {
        alert(this.name);
    };
}
//同样的,第一个参数仍是 this,第二个参数是只有一个值 color 的数组。可以把 ClassB 的整个 arguments 对象作为第二个参数传递给 apply() 方法:
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);
    };
}
//缺点 因为是对象冒充,所以只能继承 父类中用 this 定义的属性和方法,二对于prototype 定义的不能继承

//---------------《三》、原型链(prototype chaining)-----------------------
/* 在上一章学过,prototype 对象是个模板,要实例化的对象都以这个模板为基础。
* 总而言之,prototype 对象的任何属性和方法都被传递给那个类的所有实例。原型链利用这种功能来实现继承机制。
*/
function ClassA() {}

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

ClassB.prototype = new ClassA();//原型方式的神奇之处在这里,把 ClassB 的 prototype 属性设置成 ClassA 的实例。
//注意:调用 ClassA 的构造函数,没有给它传递参数。这在原型链中是标准做法。要确保构造函数没有任何参数。
//此外,在原型链中,instanceof 运算符的运行方式也很独特。对 ClassB 的所有实例,instanceof 为 ClassA 和 ClassB 都返回 true。例如:
var objB = new ClassB();
alert(objB instanceof ClassA); //输出 "true"
alert(objB instanceof ClassB); //输出 "true"

//原型链的弊端是不支持多重继承。记住,原型链会用另一类型的对象重写类的 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 方法前。应为该行是从写ClassB 的 原型模板,所以在之前定义的原型方法将丢失

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

/*=============================================================
*     关于js 类的创建和继承 终结                 |
*              《最佳实现方式》                           |
*     ---根据http://www.w3school.com.cn 总结而来    |
//=============================================================*/
/* 类的定义使用《原型方式》(不浪费内存)
*   继承使用 《混合方式》(冒充和原型结合)
*   代码如下:
*/
var ShowForm=function(options,formID){
 this.opt = {
  renderto:'body',
  formBasePriceBlock:'#basePrice',
  forQue_TotalCostBlock:'#preferredOption',
  formTotalCostBlock:'#totalCost'
 };
 
 $.extend(this.opt, options);//使用了Jquery ,扩展opt对象(有则重写,没有则加入,请参考Jquery $.extend() )
 
 this.init(formID);
 this.itemCount=0;
    this.fb_itemIDName='fb-item-'; 
};
ShowForm.prototype.methodA(){};
ShowForm.prototype.methodB(variableA){};
ShowForm.prototype.methodC(variableA,variableB,variableC){};
//使用
var testObjt=new ShowForm({ //创建对象,并传一个对象到构造函数
 renderto:'#myDocID',
});
//继承
function ClassB(sColor, sName) {
    ShowForm.call(this, {});
    this.name = sName;
}

ClassB.prototype = new ClassA();
ClassB.prototype.methodInClassB=function(){};

//结合完整实例:
var ShowForm=function(options){
 this.opt = {
  renderto:'body',
  formBasePriceBlock:'#basePrice',
  forQue_TotalCostBlock:'#preferredOption',
  formTotalCostBlock:'#totalCost',
  color:'red',
  name:'showForm'
 };
 
 $.extend(this.opt, options);//使用了Jquery ,扩展opt对象(有则重写,没有则加入,请参考Jquery $.extend() )
 
 //this.init(formID);
 this.iItemCount=0;
    this.sFb_itemIDName='fb-item-'; 
};
ShowForm.prototype.methodA=function(){
 alert('color:'+this.opt.color+',name:'+this.opt.name);
};
ShowForm.prototype.methodB=function(variableA){
 return this.bname;//访问子类的属性,是可以的
};
ShowForm.prototype.methodC=function(){

 return this.opt.formBasePriceBlock;
};
ShowForm.prototype.methodD=function(variableA,variableB,variableC){};

function ClassB(sColor, sName) {
    this.bname = 'Bname';
 ShowForm.call(this,{
      color:sColor,
      name:sName
     }//传一个对象给父类
    );
    //this.name = sName;
}
ClassB.prototype = new ShowForm();

ClassB.prototype.methodInClassA=function(){
 alert("methodInClassA access ShowForm's attribute,renderto:"+this.opt.renderto);
};
ClassB.prototype.methodInClassB=function(){
 alert("methodInClassB access ShowForm's methodB:"+this.methodB());
};
ClassB.prototype.methodInClassC=function(){
 alert("methodInClassC access ShowForm's methodC:"+this.methodC());
};

var  testObj=new ClassB('blue','yellow');
testObj.methodA();   //输出 color:blue,name:yellow
testObj.methodInClassA(); //输出 methodInClassA access ShowForm's attribute,renderto:body
testObj.methodInClassB(); //输出 methodInClassB access ShowForm's methodB:Bname
testObj.methodInClassC();   //输出 methodInClassC access ShowForm's methodC:#basePrice

原创粉丝点击