利用闭包的概念,JavaScript中不但有公有和私有的特性,而且它的公有和私有性,比起其它各种面向对象语言毫不逊色。下面给出一个例子:
例21.2 对象的公有和私有特性
function List()
{
var m_elements = []; //私有成员,在对象外无法访问
m_elements = Array.apply(m_elements, arguments);
//公有属性,可以通过“.”运算符或下标来访问
this.length = {
valueOf:function(){
return m_elements.length;
},
toString:function(){
return m_elements.length;
}
}
this.toString = function()
{
return m_elements.toString();
}
this.add = function()
{
m_elements.push.apply(m_elements, arguments);
}
}
function List定义了一个List类,该类接受一个参数列表,该列表中的成员为List的成员。m_elements是一个私有成员,在类的定义域外部是无法访 问的。this.length、this.toString和this.add是公有成员,其中this.lenght是私有成员m_elements的 length属性的getter,在外部我们可以通过对象名的“.”运算符对这些属性进行访问,例如:
var alist = new List(1,2,3);
alert(alist);
alert(alist.length);
alist.push(4,5,6);
alert(alist);
alert(alist.length);
小技巧:对象 的getter是一种特殊的属性,它形式上像是变量或者对象属性,但是它的值随着对象的某些参数改变而变化。在不支持getter的语言中,我们通常用 get<Name>方法来代替getter,其中<Name>是getter的实际名字,这种用法产生的效果和getter等 价,但是形式上不够简洁。ECMAScript v3不支持getter,但是可以用上面这种构造带有自定义valueOf和toString方法的对象来巧妙地模拟getter。
例如,下面的两段代码基本上等价:
//第一段代码:使用getName()方式
function Foo(a, b)
{
this.a = a;
this.b = b;
this.getSum = function()
{
return a+b;
}
}
alert((new Foo(1,2)).getSum()); //得到3
//第二段代码:模拟getter
function Foo(a, b)
{
this.a = a;
this.b = b;
this.sum = {
valueOf:function(){ return a+b},
toString:function(){return a+b}
}
}
alert((new Foo(1,2)).sum); //同样得到3
对 象的setter是另一个相对应的属性,它的作用是通过类似赋值的方式改变对象的某些参数或者状态,遗憾的是,ECMAScript v3不支持setter,并且目前为止也没有什么好的办法可以在JavaScript上模拟setter。要实现setter的效果,只有通过定义 set<Name>方法来实现。