有一個避免其他程式員無意間寫出重名函數的辦法,在你想作為私有屬性或者私有方法的命名前加一個下劃線,像這樣 this._name = name;,這樣雖然不能避免所有的錯誤,但是能夠避免絕大多數的無意識命名引起的沖突。
Scope,Nested Functions,and Closures
在實作私有屬性的封裝之前,我們需要一些基礎的概念支援。在Javascript中,隻有函數擁有作用域,也就是說,函數内部定義的變量,在外部是無法通路的。隻有函數外部定義的變量,在函數内部才能通路。下面是一個說明的例子:
function foo(){
var = 10;
function bar(){
a *= 2;
}
bar();
return a;
在這個例子中,a被定義在foo函數中,可是函數bar中可以通路a,是因為bar函數被定義在了foo函數中。當bar被執行時,他就能夠使a的值翻倍,這是bar在foo内部執行,如果bar在foo外部執行會怎麼樣呢,看下面的例子:
var a = 10;
a *= 2;
return a;
return bar;
var baz = foo();
baz(); //傳回20;
baz(); //傳回40;
baz(); //傳回80;
上例中函數傳回的是一個對于bar的引用,把這個引用傳遞給baz,在執行的時候,他仍可以通路變量a。這是為什麼呢?因為Javascript支援語義上作用域,函數運作是在他被定義的域中,而不是他在被執行的域中。這個例子中bar因為被定義在foo的内部,是以當他在外部被執行時,仍然可以通路内部的變量a。
以上就是一個Closure的例子,隻有foo中被傳回的函數能夠通路foo中的變量,最常見的建立Closure的方法就是傳回一個Nested Function。
利用Closure建立私有方法
有了上面的基礎,我們就能夠實作私有方法了,如下:
var
NewHouse
=
function(hid,hname,address){
var
_hid,_hname,_address;
function
isValid(hid){
if(hid
!=
null
&&
hid
undefined
&
""){
return
true;
}else{
false;
}
}
this.getHid
function(){
return
_hid;
this.setHid
function(hid){
if(!isValid(hid)){
_hid
hid;
this.getHname
_hname;
this.setHname
function(hname){
_hname
hname
||
"暫無";
this.getAddress
_address;
this.setAddress
function(address){
_address
address
this.setHid(hid);
this.setHname(hname);
this.setAddress(address);
}
NewHouse.prototype.ShowHouse
document.getElementById("container").innerHTML
+=
"樓盤名稱:"
+
this.hname
"<br />";
可以看到,之前的例子中一直用this關鍵字來引用屬性,而我們這裡用了var來定義屬性,是以屬性在對象外是不能夠被通路的。對于一些公共的方法,我們仍然可以利用prototype來定義他們。
這個方法的缺陷是我們每建一個對象,對于内部的方法對要被初始化一下,而這是要消耗記憶體的,我們執行個體的對象越多,消耗的記憶體也就越多。是以這個方法隻試用在真正需要私有化屬性和方法的地方,其他的地方我們仍然可以用完全暴露的方法來做。