|
1
2
3
4
|
function
add(num1,num2){
var
sum=num1+num2;
return
sum;
}
|
在這個函數內部,有3個私有變量:num1、num2和sum。如果在這個函數內部創建一個閉包,那么閉包通過自己的作用域鏈也可以訪問這些變量,利用這一點,就可以創建用於訪問私有變量的公用方法。
我們把有權訪問私有變量和私有函數的公有方法叫做特權方法。
1.構造函數定義法
有兩種在對象上創建特權方法的方式。第一種是在構造函數中定義特權方法,基本模式如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
function myobject
(){
//私有屬性和私有函數
var
privateVariable=10;
function
privatevateFunction(){
return
false
;
}
//特權方法
this
.publicMethod=
function
(){
privateVariable++;
return
privatevateFunction();
};
}
|
這個模式在函數內部定義了所有私有變量和函數。然后,又繼續創建了能夠訪問這些私有成員的特權方法。能夠在構造函數中定義特權方法,是因為特權方法作為閉包有權訪問在構造函數中的所有變量和函數。
利用私有和特權方法,可以隱藏那些不該被直接修改的數據,例如:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
function
Persom(name){
this
.getName=
function
(){
return
name;
};
this
.setName=
function
(value){
name=value;
};
}
var
person=
new
Person(
"zxj"
);
alert(person.getName());
//zxj
person.setName(
"Greg"
);
alert(person.getName());
//Greg
|
在以上構造函數中定義了兩個特權方法:getName()和setName()。這兩個方法都可以在函數外部使用,而且都有權訪問私有變量name。
構造函數定義法,也是構造函數,構造函數有的缺點,它同樣也存在。
2.靜態私有變量
通過在私有作用域中定義私有變量或函數,同樣也可以創建特權方法,基本模式如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
(
function
(){
//私有變量和私有函數
var
privateVariable=10;
function
privareFunction(){
return
false
;
};
//構造函數
MyObject=
function
(){
};
//公有/特權方法
MyObject.prototype.publicMethod=
function
(){
privateVariable++;
privareFunction();
};
}
)()
|
這個模式創建了一個私有作用域,並在其中封裝了一個構造函數級相應的方法。在私有作用域中,首先定義了私有變量和私有函數,然后定義了一個構造函數及其公有方法。公有方法是在原型上定義的,這一點體現了典型的原型模式。需要注意的是,這個模式在定義構造函數是並沒有使用函數聲明,而是使用的函數表達式。函數聲明只能創建局部函數,出於相同原因,在聲明MyObject時也沒使用var.記住:初始化未經聲明的變量,總會創建一個全局變量。因此,MyObject就成了全局變量,能夠在私有作用域之外被訪問。
與構造函數定義特權的區別在於:私有變量和函數是由實例共享的。由於特權方法是在原型上定義的,因此所有實例都使用同一個函數。而這個特權方法,作為閉包,總是保存着對包含作用域的引用。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
(
function
(){
var
name =
""
;
Person =
function
(value){
name = value;
};
Person.prototype.getName =
function
(){
return
name;
};
Person.prototype.setName =
function
(value){
name = value;
};
})();
var
person1 =
new
Person(
"zxj"
);
alert(person1.getName());
//"zxj"
person1.setName(
"Greg"
);
alert(person1.getName());
//"Greg"
var
person2 =
new
Person(
"Michael"
);
alert(person1.getName());
//"Michael"
alert(person2.getName());
//"Michael"
|
一這種方式創建靜態私有變量會因為使用原型而增進代碼的復用,但每個實例都沒有自己的私有變量。到底使用實例變量還是靜態私有變量,最終還是有具體業務決定。
3.模塊模式
前面模式用於自定義類型創建私有變量和特權方法。
模塊模式是為單例創建私有變量和特權方法,單例就是指,只有一個實例的對象。
JavaScript是以對象字面量的方式創建單例對象的。
|
1
2
3
4
5
6
|
var
singlton={
name:value,
method:
function
{
//這是方法的代碼
}
}
|
模塊模式通過單例添加私有變量和特權放哪廣發能夠使其得到增強,基本形式如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
var
singlton=
function
{
//私有變量和私有函數
var
privateVaiable=
10
;
function
privateMethod(){
return
false
;
};
//公有/特權方法
return
{
publicProperty:
true
,
piblicMethod:
function
(){
privateVaiable++;
return
privateMethod();
}
}
}();
|
這個模塊使用了一個返回對象的匿名函數。在這個匿名函數內部,首先定義了私有變量和函數。然后,將一個對象字面量作為函數的值返回。返回的對象字面量中只包含可以公開的屬性和方法。由於這個對象是在匿名函數內部定義的,因此它的公有方法有權訪問私有變量和函數。從本質上講,這個對象字面量定義的是單例的公共接口。這種模式在需要對單例進行某些初始化,同時有需要維持其私有變量時是非常有用的,如
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
function
BaseComponent(){
}
function
OtherComponent(){
}
var
application =
function
(){
//私有變量和函數
var
components =
new
Array();
//初始化
components.push(
new
BaseComponent());
//公有
return
{
getComponentCount :
function
(){
return
components.length;
},
registerComponent :
function
(component){
if
(
typeof
component ==
"object"
){
components.push(component);
}
}
};
}();
application.registerComponent(
new
OtherComponent());
alert(application.getComponentCount());
//2
|
這個簡單的例子創建了一個用於管理組件的application對象。在創建這個對象的過程中,首先聲明了一個私有的components數組,並向數組中添加一個BaseComponent的新實例(這里不需要關心BaseComponent的代碼,我們只是用他來展示初始化操作)。而返回對象的getComponentCount()和registerComponent ()方法,都有權訪問數組components的特權方法。前者只是發那個會已注冊的組件數目,后則用於注冊新組件。
一這種模式創建的每一個單例都是Object的實例,因為最終要通過一個對象字面量來表示它。單例通常都是作為全局對象存在的。
4.增強的模塊模式
增強的模塊模式適合那些單例必須是某種類型的實例,同時還必須添加某些屬性或(和)方法對齊加以增強的情況。如下所示:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
var
singlton=
function
{
//私有變量和私有函數
var
privateVaiable=10;
function
privateMethod(){
return
false
;
};
//創建對象
var
object=
new
CustomType();
//公有/特權方法
object.publicProperty=
true
;
object.piblicMethod=
function
(){
privateVaiable++;
return
privateMethod();
};
//返回這個對象
return
object;
}();
|
如果前面演示模塊模式的例子中的application對象必須是BaseComponent的實例,我們可以使用一下代碼:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
function
BaseComponent(){
}
function
OtherComponent(){
}
var
application =
function
(){
//私有變量和私有函數
var
components =
new
Array();
//創建對象
components.push(
new
BaseComponent());
//創建application的一個局部副本
var
app =
new
BaseComponent();
//公共
app.getComponentCount =
function
(){
return
components.length;
};
app.registerComponent =
function
(component){
if
(
typeof
component ==
"object"
){
components.push(component);
}
};
//返回這個副本
return
app;
}();
alert(application
instanceof
BaseComponent);
application.registerComponent(
new
OtherComponent());
alert(application.getComponentCount());
//2
|
