JavaScript学习笔记——继承

JavaScript学习笔记——继承
 

说明:本文为《JavaScript高级程序设计》第4章学习笔记。

一.             继承机制实例

几何形状只有两种,即椭圆形和多变形。圆是椭圆形的一种,它只有一个焦点。三角形、矩形和五边形都是多边形的一种,具有不同数量的边。正方形是矩形的一种,所有的边等长。这就构成了继承关系。

形状是椭圆形和多边形的基类。圆形继承了椭圆形,因此圆形是椭圆形的子类,椭圆形是圆形的超类

二.             继承机制的实现

要用ECMAScript实现继承机制,首先从基类入手。所有开发者定义的类都可以作为基类。出于安全原因,本地类和宿主类不能作为基类,这样可以防止编译过的浏览器级的代码,因为这些代码可以被用于恶意攻击。

选定基类后,就可以创建它的子类了。是否使用基类完全由你决定。有时,你可能想创建不能直接使用的基类,它只是用户给予类公共通用的函数。在这种情况下,基类被看作抽象类

1.继承的方式

JavaScript中的继承机制并不是明确规定的,而是通过模仿实现的。开发者可以自己决定最适用的继承方式。

1)对象冒充

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

Eg. 

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


2)call()方法

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

Eg. 可将上例中的ClassB改成如下后,可达到先前同样的效果: 

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

}

 

3)apply()方法

该方法有两个参数,用作this的对象要传递给的参数的数组。

Eg.

function  sayColor(sPrefix, sSuffix)  {
          alert(sPrefix 
+ this.color + sSuffix);
}
;
var  obj  =   new  Object();
obj.color 
=   " red " ;
sayColor.apply(obj, 
new  Array( " The color is  " " , a very nice color indeed. " ));

可将上述的ClassB修改为如下这样:

function  ClassB(sColor, sName)  {
       ClassA.apply(
thisnew Array(sColor));
       
this.name = sName;
       
this.sayName = function() {
       alert(
this.name);
}
;
}

 

4)原型链

Prototype对象是个模板,要实例化的对象都以这个模板为基础。总而言之,prototype对象的任何属性和方法都被传递给那个类的所有实例。原型链利用这种功能来实现继承机制。

Eg.

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

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

5)混合模式

对象冒充的主要问题是必须使用构造函数的方式,这不是最好的选择。不过如果使用原型链,就无需使用构造函数了。如果将这两种方式混合起来,将会达到更好的效果。

Eg.

 fuction 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 
=   function ()  {
    alert(
this.name);
}
;

  调用代码如下所示:

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

 

2.一个更实际的例子

下面讲一个PolygonTriangleRectangle的例子。

1)创建基类Polygon

Eg. 

  function  Polygon(iSides)  {
         
this.sides = iSides;
}


Polygon.prototype.getArea 
=   function ()  {
        
return 0;
}
;


 

2)创建子类

三角形Triangle的内容如下:

function  Triangle(iBase, iHeight)  {
        Polygon.call(
this3);
        
this.base = iBase;
        
this.height = iHeight;
}


Triangle.prototype 
=   new  Polygon();
Triangle.prototype.getArea 
=   function ()  {
        
return 0.5 * this.base * this.height;
}
;

Rectangle的ECMAScript代码如下:

function  Rectangle(iLength; iWidth)  {
        Polygon.call(
this4);
        
this.length = iLength;
        
this.width = iWidth;
}


Rectangle.prototype 
=   new  Polygon();
Rectangle.prototype 
=   function ()  {
        
return this.length * this.width;
}
;

 

3)测试代码 

var  triangle  =   new  Triangle( 12 4 );
var  rectangle  =   new  Rectangle( 22 10 );
alert(triangle.sides);
alert(triangle.getArea());
alert(rectangle.sides);
alert(rectangle.getArea());

 

4)采用动态原型方法如何?

function  Polygon(iSides)  {
        
this.sides = iSides;
        
if (typeof Polygon._initialized == "undefined"{
       Polygon.prototype.getArea 
= function() {
       
return 0;
}
;

Polygon._initialized 
= true;
}

}


function  Triangle(iBase, iHeight)  {
        Polygon.call(
this3);
        
this.base = iBase;
        
this.height = iHeight;
        
if (typeof Triangle._initialized == "undefined"{
       Triangle.prototype 
= new Polygon();
       Triangle.prototype.getArea 
= function() {
       
return 0.5 * this.base * this.height;
}
;

Triangle. _initialized 
= true;
}

}


Triangle.prototype 
=   new  Polygon();

 

三.             小结

本章介绍了ECMAScript中用对象冒充和原型链实现的继承概念。学会结合使用这些方式才是建立类之间的继承机制的最好方式。

你可能感兴趣的:(JavaScript学习笔记——继承)