說明:本文為《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(this, new 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.一個更實際的例子
下面講一個Polygon、Triangle和Rectangle的例子。
1)創建基類Polygon
Eg.

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


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



2)創建子類
三角形Triangle的內容如下:

function Triangle(iBase, iHeight)
{
Polygon.call(this, 3);
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(this, 4);
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(this, 3);
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中用對象冒充和原型鏈實現的繼承概念。學會結合使用這些方式才是建立類之間的繼承機制的最好方式。
posted on 2007-09-04 08:59
阿蜜果 閱讀(956)
評論(3) 編輯 收藏 所屬分類:
Javascript