[size=xx-large]js 对象[/size]
私有静态成员
前面在基本概念里我们已经清楚了,只有用 function 创建函数,才能创建一个新的作用域,而要创建私有成员(不论是静态成员,还是实例成员),都需要通过创建新的作用域才能够起到数据隐藏的目的。下面所采用的方法就是基于这一点来实现的。
实现私有静态成员是通过创建一个匿名函数函数来创建一个新的作用域来实现的。
通常我们使用匿名函数时都是将它赋值给一个变量,然后通过这个变量引用该匿名函数。这种情况下,该匿名函数可以被反复调用或者作为类去创建对象。而这里,我们创建的匿名函数不赋值给任何变量,在它创建后立即执行,或者立即实例化为一个对象,并且该对象也不赋值给任何变量,这种情况下,该函数本身或者它实例化后的对象都不能够被再次存取,因此它唯一的作用就是创建了一个新的作用域,并隔离了它内部的所有局部变量和函数。因此,这些局部变量和函数就成了我们所需要的私有静态成员。而这个立即执行的匿名函数或者立即实例化的匿名函数我们称它为静态封装环境。
下面我们先来看通过直接调用匿名函数方式来创建带有私有静态成员的类的例子:
class5 = (function() {
// private static fields
var s_first = 1;
var s_second = 2;
// private static methods
function s_method1() {
s_first++;
}
var s_second = 2;
function constructor() {
// private fields
var m_first = 1;
var m_second = 2;
// private methods
function method1() {
alert(m_first);
}
var method2 = function() {
alert(m_second);
}
// public fields
this.first = "first";
this.second = ['s','e','c','o','n','d'];
// public methods
this.method1 = function() {
s_second--;
}
this.method2 = function() {
alert(this.second);
}
// constructor
{
s_method1();
this.method1();
}
}
// public static methods
constructor.method1 = function() {
s_first++;
alert(s_first);
}
constructor.method2 = function() {
alert(s_second);
}
return constructor;
})();
var o1 = new class5();
class5.method1();
class5.method2();
o1.method2();
var o2 = new class5();
class5.method1();
class5.method2();
o2.method2();
这个例子中,通过
(function() {
...
function contructor () {
...
}
return constructor;
})();
来创建了一个静态封装环境,实际的类是在这个环境中定义的,并且在最后通过 return 语句将最后的类返回给我们的全局变量 class5,然后我们就可以通过 class5 来引用这个带有静态私有成员的类了。
为了区分私有静态成员和私有实例成员,我们在私有静态成员前面用了 s_ 前缀,在私有实例成员前面加了 m_ 前缀,这样避免了重名,因此在对象中总是可以存取私有静态成员的。
但是这种命名方式不是必须的,只是推荐的,私有静态成员可以跟私有实例成员同名,在重名的情况下,在类构造器和在类中定义的实例方法中存取的都是私有实例成员,在静态方法(不论是公有静态方法还是私有静态方法)中存取的都是私有静态成员。
在类外并且在静态封装环境中通过 prototype 方式定义的公有实例方法存取的是私有静态成员。
在静态封装环境外定义的公有静态方法和通过 prototype 方式定义的公有实例方法无法直接存取私有静态成员。
另外一种方式通过直接实例化匿名函数方式来创建带有私有静态成员的类的例子跟上面的例子很相似:
new function() {
// private static fields
var s_first = 1;
var s_second = 2;
// private static methods
function s_method1() {
s_first++;
}
var s_second = 2;
class6 = function() {
// private fields
var m_first = 1;
var m_second = 2;
// private methods
function method1() {
alert(m_first);
}
var method2 = function() {
alert(m_second);
}
// public fields
this.first = "first";
this.second = ['s','e','c','o','n','d'];
// public methods
this.method1 = function() {
s_second--;
}
this.method2 = function() {
alert(this.second);
}
// constructor
{
s_method1();
this.method1();
}
}
// public static methods
class6.method1 = function() {
s_first++;
alert(s_first);
}
class6.method2 = function() {
alert(s_second);
}
};
var o1 = new class6();
class6.method1();
class6.method2();
o1.method2();
var o2 = new class6();
class6.method1();
class6.method2();
o2.method2();
这个例子的结果跟通过第一种方式创建的例子是相同的。只不过它的静态封装环境是这样的:
new function() {
...
};
在这里,该函数没有返回值,并且对于 class5 的定义是直接在静态封装环境内部通过给一个没有用 var 定义的变量赋值的方式实现的。
当然,也完全可以在
(function() {
...
})();
这种方式中,不给该函数定义返回值,而直接在静态封装环境内部通过给一个没有用 var 定义的变量赋值的方式来实现带有私有静态成员的类的定义。
这两种方式在这里是等价的。
私有静态成员
前面在基本概念里我们已经清楚了,只有用 function 创建函数,才能创建一个新的作用域,而要创建私有成员(不论是静态成员,还是实例成员),都需要通过创建新的作用域才能够起到数据隐藏的目的。下面所采用的方法就是基于这一点来实现的。
实现私有静态成员是通过创建一个匿名函数函数来创建一个新的作用域来实现的。
通常我们使用匿名函数时都是将它赋值给一个变量,然后通过这个变量引用该匿名函数。这种情况下,该匿名函数可以被反复调用或者作为类去创建对象。而这里,我们创建的匿名函数不赋值给任何变量,在它创建后立即执行,或者立即实例化为一个对象,并且该对象也不赋值给任何变量,这种情况下,该函数本身或者它实例化后的对象都不能够被再次存取,因此它唯一的作用就是创建了一个新的作用域,并隔离了它内部的所有局部变量和函数。因此,这些局部变量和函数就成了我们所需要的私有静态成员。而这个立即执行的匿名函数或者立即实例化的匿名函数我们称它为静态封装环境。
下面我们先来看通过直接调用匿名函数方式来创建带有私有静态成员的类的例子:
class5 = (function() {
// private static fields
var s_first = 1;
var s_second = 2;
// private static methods
function s_method1() {
s_first++;
}
var s_second = 2;
function constructor() {
// private fields
var m_first = 1;
var m_second = 2;
// private methods
function method1() {
alert(m_first);
}
var method2 = function() {
alert(m_second);
}
// public fields
this.first = "first";
this.second = ['s','e','c','o','n','d'];
// public methods
this.method1 = function() {
s_second--;
}
this.method2 = function() {
alert(this.second);
}
// constructor
{
s_method1();
this.method1();
}
}
// public static methods
constructor.method1 = function() {
s_first++;
alert(s_first);
}
constructor.method2 = function() {
alert(s_second);
}
return constructor;
})();
var o1 = new class5();
class5.method1();
class5.method2();
o1.method2();
var o2 = new class5();
class5.method1();
class5.method2();
o2.method2();
这个例子中,通过
(function() {
...
function contructor () {
...
}
return constructor;
})();
来创建了一个静态封装环境,实际的类是在这个环境中定义的,并且在最后通过 return 语句将最后的类返回给我们的全局变量 class5,然后我们就可以通过 class5 来引用这个带有静态私有成员的类了。
为了区分私有静态成员和私有实例成员,我们在私有静态成员前面用了 s_ 前缀,在私有实例成员前面加了 m_ 前缀,这样避免了重名,因此在对象中总是可以存取私有静态成员的。
但是这种命名方式不是必须的,只是推荐的,私有静态成员可以跟私有实例成员同名,在重名的情况下,在类构造器和在类中定义的实例方法中存取的都是私有实例成员,在静态方法(不论是公有静态方法还是私有静态方法)中存取的都是私有静态成员。
在类外并且在静态封装环境中通过 prototype 方式定义的公有实例方法存取的是私有静态成员。
在静态封装环境外定义的公有静态方法和通过 prototype 方式定义的公有实例方法无法直接存取私有静态成员。
另外一种方式通过直接实例化匿名函数方式来创建带有私有静态成员的类的例子跟上面的例子很相似:
new function() {
// private static fields
var s_first = 1;
var s_second = 2;
// private static methods
function s_method1() {
s_first++;
}
var s_second = 2;
class6 = function() {
// private fields
var m_first = 1;
var m_second = 2;
// private methods
function method1() {
alert(m_first);
}
var method2 = function() {
alert(m_second);
}
// public fields
this.first = "first";
this.second = ['s','e','c','o','n','d'];
// public methods
this.method1 = function() {
s_second--;
}
this.method2 = function() {
alert(this.second);
}
// constructor
{
s_method1();
this.method1();
}
}
// public static methods
class6.method1 = function() {
s_first++;
alert(s_first);
}
class6.method2 = function() {
alert(s_second);
}
};
var o1 = new class6();
class6.method1();
class6.method2();
o1.method2();
var o2 = new class6();
class6.method1();
class6.method2();
o2.method2();
这个例子的结果跟通过第一种方式创建的例子是相同的。只不过它的静态封装环境是这样的:
new function() {
...
};
在这里,该函数没有返回值,并且对于 class5 的定义是直接在静态封装环境内部通过给一个没有用 var 定义的变量赋值的方式实现的。
当然,也完全可以在
(function() {
...
})();
这种方式中,不给该函数定义返回值,而直接在静态封装环境内部通过给一个没有用 var 定义的变量赋值的方式来实现带有私有静态成员的类的定义。
这两种方式在这里是等价的。