享元類就是類的類型,即創建類型的類。享元類與類的關係正如類與對象的關係一樣,是一種創建型的泛化關係。享元類能夠接受類作為參數,即享元類操作的對象是類,而不是具體的數據。一般享元類返回的是類,而不是具體的數據。下面的示例就是一個簡單的享元類,它包含了一個返回的類。
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);//提示編譯錯誤,沒有這個成員