讀古今文學網 > 編寫高質量代碼:改善JavaScript程序的188個建議 > 建議102:使用享元類 >

建議102:使用享元類

享元類就是類的類型,即創建類型的類。享元類與類的關係正如類與對象的關係一樣,是一種創建型的泛化關係。享元類能夠接受類作為參數,即享元類操作的對象是類,而不是具體的數據。一般享元類返回的是類,而不是具體的數據。下面的示例就是一個簡單的享元類,它包含了一個返回的類。


function O(x){//享元類

return function{//類

this.x=x;

this.get=function{

alert(this.x);

}

}

}

var o=new O(1);

var f=new o;

f.get;//調用返回類的方法get,返回1


從上面的示例可以看到,享元類與普通函數沒有什麼兩樣,不過它的返回值是類,而不是具體數值。實際上,JavaScript核心對像Function就是一個享元類,雖然說它沒有返回值,但是我們可以通過字符串的形式創建返回類。例如:


var O=new Function("this.x=1;this.y=2")//實例化之後返回的是類

var o=new O;//實例化返回類

alert(o.x);//調用實例的屬性值,返回1


上面的示例演示了簡單的函數中包含一個返回類結構,當然享元類並非如此簡單。下面再演示一個比較複雜的示例,在這個享元類中參數值包含類類型,返回值也是類類型。

首先,定義一個普通類,作為一個參數值準備傳遞給享元類。


function F(x,y){

this.x=x;

this.y=y;

}

F.prototype.add=function{

alert(this.x+this.y);

}


然後,定義一個享元類,該函數類包含3個參數,其中第一個參數為類類型,第二個和第三個參數是值類型數據。


function O(o,x,y){

this.say=function{

alert("享元類");

}

return function{

this.say=function{

alert("返回類");

}

var a=new o(x,y);//實例化參數類

for(var i in a){//通過實例繼承法,繼承參數類給返回類

this[i]=a[i];//此時this關鍵字只返回類的當前對像

}

}

}


最後,使用new運算符調用享元類,第一個參數值為上文定義的類F,第二個和第三個參數為普通數值,返回的類賦值給變量A,則A就變成了一個類結構。此時不能夠通過A來讀取享元類的本地方法say。


var A=new O(F,1,2);

var B=new A;

A.say;//如果直接調用享元類的本地方法,將提示編譯錯誤


但可以通過實例化後的B對像來訪問參數類F中的成員,以及返回類內部定義的本地屬性。


B.say;//字符串"返回類"

B.add;//數值3

alert(B.x);//數值1

alert(B.y);//數值2


注意,當一個類有返回值時,如果是值類型數據,則可以訪問類的成員,也可以獲取返回值。


function F{

this.x=1;

return 2;

}

var f=new F;

alert(f.x);//1

alert(F);//2


如果類返回的是引用類型或函數體,則類的成員將不可訪問,它們將成為閉包結構內的私有數據,不再對外開放。


function F{

this.x=1;

return function{

return this.x;

};

}

F.prototype.y=function{

alert(3);

}

var f=new F;

alert(f.x);//訪問本地屬性x失敗,返回undefined

alert(F);//調用返回的函數,返回1,說明它可以訪問本地屬性x

alert(f.y);//提示編譯錯誤,沒有這個成員