享元类就是类的类型,即创建类型的类。享元类与类的关系正如类与对象的关系一样,是一种创建型的泛化关系。享元类能够接受类作为参数,即享元类操作的对象是类,而不是具体的数据。一般享元类返回的是类,而不是具体的数据。下面的示例就是一个简单的享元类,它包含了一个返回的类。
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);//提示编译错误,没有这个成员