[1] 對象偽裝法 (Object Masquerading)
對象偽裝法實際是程式員為了實現繼承的 Trick
繼承:ClassB 繼承 ClassA,注意 delete this.newMethod 的使用。
程式碼/* ClassA 的原始定義 */
function ClassA(sColor) {
this.color = sColor;
this.sayColor = function(){
alert(this.color);
}
}
/* ClassB 的原始定義 */
function ClassB(sColor) {}
/* ClassB 定義2 */
function ClassB(sColor) {
this.newMethod = ClassA;
this.newMethod(sColor);
delete this.newMethod; //刪除對ClassA的引用,避免以後被調用
}
/* ClassB 定義3 */
function ClassB(sColor, sName) {
this.newMethod = ClassA;
this.newMethod(sColor);
delete this.newMethod;
this.name = sName;
this.sayName = function() {
alert(this.name);
}
}
[2] 多重繼承
ClassZ繼承自ClassX與ClassY
程式碼function ClassZ() {
this.newMethod = ClassX;
this.newMethod();
delete this.newMethod;
this.newMethod = ClassY;
this.newMethod();
delete this.newMethod;
}
上述的實現有一個Gotcha,當ClassX與ClassY有同名的屬性或方法時,因為ClassY後初始化,所以會覆蓋掉ClassX的同名方法或屬性。
[3] 使用call()方法實現
call()方法的第一參數為被當作This的對象,其他參數直接被傳給funciton,通過使用Call(),我們也可以實現繼承:
程式碼function ClassB(sColor, sName) {
ClassA.call(this, sColor);
this.name = sName;
this.sayName = function() {
alert(this.name);
}
}
[4] 使用Apply()方法實現
Apply()方法只有兩個參數,第一個與call()一樣,被當作this;第二個是被傳入function的參數數組,使用Apply()的好處是你可以使用function的arguments對象直接當作第二參數。
程式碼function ClassB(sColor, sName) {
ClassA.apply(this, arguments); // 註:參數的順序必須和ClassA定義的順序一致
this.name = sName;
this.sayName = function() {
alert(this.name);
}
}
注意:如果使用arguments對象則需保證參數順序與ClassA一致。
[5] 使用Prototype鏈
要求構造器不能有參數
程式碼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);
}
好處是可以使用instanceof,對對象進行判斷,如果obj為ClassB對象,則instanceof ClassA和ClassB都會為true,這是使用偽裝法所不具備的,但是prototype的構造器不能有參數。所以最好的方式是混合法。
[6] 使用混合法 程式碼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);
}
但是混合法的缺點是無法多重繼承。
[7] 動態原形法的一些問題
主要指xxx.protoype = new xxx() 不能被放在構造器裡面,必須放在外面,可是如果要放在外面,那動態原形法本身就失去意義了,因為動態原形法本身就是為了把原形方法放在function的構造器裡面,以使得代碼風格接近Java。所以最好還是不要用動態原形法了。
[8] 利用其它通過工具庫實現繼承
xbObject(http://archive.bclary.com/xbProjects/)
Zinherit (Nicholas C. Zakas的庫,Professional Javascript for web developer的作者)