JavaScript中的面向对象编程(二)

对象冒充,apply()方法 Call()方法 原型链(利用prototype对象来实现.

 

 

 

Javaspript的继承

JavaScript中的继承

特点:

1ECMAScript中并没有像其他语言那样严格地定义抽象类.

2、所有类的方法都是public的作用域

3、继承的方式不止一种,支持多重继承

严格讲,javascript的继承机制并不是明确规定的,而是通过模仿实现的。

对象冒充

   其原理如下:构造函数使用this关键字给所有属性和方法赋值.因为构造函数只是一个函数,所以可使用ClassA的构造函数成为ClassB的方法,然后调用它.ClassB就会收到ClassA的构造函数中定义的属性和方法.

eg1:

function ClassA(sColor){

    this.color = sColor;

    this.sayColor = function(){

        alert(this.color); } }

function ClassB(sColor){

   this.newMethod = ClassA;//定义新的属性指向classA

   this.newMethod(sColor);

   delete this.newMethod; 把这个属性删除掉,相当于classBclassA继承

}

注意:所有的新属性和新方法都必须在删除了新方法的代码行后定义.否则,可能会覆盖超类的相关属性和方法.

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); }}

//call

Var objA = new ClassA(“red”); Var objB = new ClassB(“blue”,”zhang”);

objA.sayColor();   //output “red”;

objB.sayColor();   //output “blue”;

objB.sayName(); //output “zhang”;

 

 

 

模仿多重继承

eg:

function ClassA(sColor)                        function ClassB(sName)

{                                            this.name = sName;

      this.color = sColor;                       this.sayName=function()

      this.sayColor=function()                  {  alert(this.name); }}

      {

           alert(this.color);

      }

}

function ClassC(sColor,sName,sModel){ //classC希望从AB继承

    this.newMethod = ClassA;

    this.newMethod(sColor);

    delete this.newMethod;

    this.newMethod =ClassB;

    this.newMethod(sName);

    delete this.newMethod;

    this.model=sModel;

    this.sayModel = function()

    {

        alert(this.model);

    }

}

//call

var cObj = new ClassC("red","zhang","T40");

cObj.sayColor();    //output “red”

cObj.sayName();   //output “zhang”;

cObj.sayModel(); //output “T40”;

 

 

 

 

注意:多重继承防止出现父类同名问题

由于这种方式的流行,ECMAScript的第三版为Function对象加入了两个新方法 Call()apply()

2Call()方法

call方法是与经典的对象冒充方法最相似的方法.它的第一个参数用作this的对象,其他参数都直接传递给函数自身.

eg:

function sayColor(sprev,snext)

{

    alert(sprev+this.color+snext); //this说明肯定有对象来调用它

 

}

var obj = new Object();

obj.color = “red”;

sayColor.call(obj,”The color is ”,”a very nice color”);会把obj对象传给saycolorthis参数

//output “The color is red ,a very nice color”

利用call关键字实现继承

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;

ClassA.call(this,sColor);

//调用calssA这个函数,传递对象是当前对象本身,并把参数传进去

    this.name = sName;

    this.sayName= function(){

       alert(this.name); }}

//call

var objB = new ClassB(“red”,”zhang”);

objB.sayColor();   //output “red”

 objB.sayName(); //output “zhang”

apply()方法 

apply()方法有两个参数,用作this的对象和要传递给函数的参数的数组.

eg:

function sayColor(sprev,snext){

    alert(sprev+this.color+snext);}

var obj = new Object();

obj.color =“red”;

sayColor.apply(obj,new Array(“The Color is “,” a very nice color”));第二个参数用数组表示,然后根据数量一一传递给调用函数//output “The color is red ,a very nice color”

利用apply关键字实现继承

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;

    ClassA.apply(this,new Array(sColor));

   this.name = sName;

    this.sayName= function(){

       alert(this.name); }}

//call

var objB = new ClassB(“red”,”zhang”);

objB.sayColor();   //output “red”

 objB.sayName(); //output “zhang”

原型链

利用prototype对象来实现.

function ClassA(){

}

ClassA.prototype.color = “red”;

ClassA.prototype.sayColor = function(){

     alert(this.color);

}

function ClassB(){

}

ClassB.prototype = new ClassA //classBclassA继承

注意,调用ClassA的构造函数时,没有给它传递参数.这在原型链中是标准做法,要确保构造函数没有任何参数.

:与对象冒充相似,子类的所有属性和方法都必须出现在prototype属性补赋值后,因为在它之前赋值的所有方法都会被删除.

eg:

function ClassB(){ //子类不能存在构造函数,否则会被classA替换掉

}

ClassB.prototype = new ClassA();

ClassB.prototype.name = “”;

ClassB.prototype.sayName = function(){

          alert(this.name);

}

//call

var objA = new ClassA();

var objB = new ClassB();

objA.color = "blue";

objB.color = "yellow";

objB.name = "zhang";

objA.sayColor(); //output “blue”

objB.sayColor(); //output “yellow”;

objB.sayName(); //output “zhang”

原型链的弊端在不支持多重继承.记住,原型链会用另一类型的对象重写类的prototype属性

混合模式

用构造函数方式定义属性,用原型方式定义方法.这种方式同样适用于继承机制.

eg:

//ClassA

function ClassA(sColor)

{

    this.color = sColor;

}

ClassA.prototype.sayColor = function(){ 

    alert(this.color);

}

//ClassB

function ClassB(sColor,sName){

     ClassA.call(this,sColor);

     this.name = sName;

}

ClassB.prototype = new ClassA();

ClassB.prototype.sayName = function(){//自己的方法sayName

     alert(this.name);

}

//call

var objA = new ClassA(“red”);

var objB = new ClassB(“blue”,”zhang”);

objA.sayColor(); //output “red”

objB.sayColor(); //output “blue” b没有sayColor方法 是从A继承的

objB.sayName(); //output “zhang”

一个更实际的例子

     //创建基类(多边形)

   function Polygon(iSides){

       this.sides = iSides;

   }

   Polygon.prototype.getArea=function(){ //原型链方法用来被继承或被重写

            return 0;

   }

   //创建子类(三角形)

   function Triangle(iBase,iHeight){

       Polygon.call(this,3);//通过继承方式设定他3个边

            this.base = iBase;

            this.height = iHeight;

   }

   Triangle.prototype = new Polygon();// 继承弗雷方法

   Triangle.prototype.getArea = function()//重写了计算面积方法

   {

        return this.base*this.height/2;

   }

   //创建子类(四边形)

   function Rectangle(iLength,iWidth){

       Polygon.call(this,4);

            this.length = iLength;

            this.width = iWidth;

   }

   Rectangle.prototype = new Polygon();

   Rectangle.prototype.getArea = function()

   {

       return this.length*this.width;

   }

   //调用

   var triangle = new Triangle(12,4);

   var rectangle = new Rectangle(22,10);

   alert(triangle.sides);   //output “3”

   alert(triangle.getArea()); //output “24”

   alert(rectangle.sides);   //output “4”;

   alert(rectangle.getArea()); //output “220”

多态

//Class Parent

   function Person(skin,language)//肤色 语言

   {

      this.skin = skin;

    this.language = language;

   }

   Person.prototype.SayHellow = function(){}

   //中国人--子类

   function China(skin,language,name)

   {

      Person.call(this,skin,language);//继承父类属性

        this.name = name;

    this.SayName = function()

    {

        alert(this.name);

    }

   }

China.prototype = new Person();//继承父类原型链方法

   China.prototype.SayHellow = function()

   {

       alert("您好");

   }

   //美国人 --子类

   function American(skin,language)

   {

      Person.call(this,skin,language);

   }

   American.prototype = new Person();

   American.prototype.SayHellow = function()

   {

      alert("hellow");

   }

 

function SayHellow(p)//多态

   {

      p.SayHellow();

   }

//-->

</SCRIPT>

</HEAD>

<BODY>

<input type="button" value="中国人的问候" onclick ="SayHellow(new China('黄色','汉语','张三'))"/>&nbsp;<input type="button" value = "美国人的问候" onclick="SayHellow(new American('白色','英语'))"/>

</BODY>

 

你可能感兴趣的:(JavaScript)