在js的懶漢式單例模式中,其實也用到了另一種設計模式,即模塊模式。在傳統軟件工程中,模塊模式被定義為給類提供私有和公共封裝的一種方法,也就是我們常說的“模塊化”。在Java里面Class就是一種模塊,解決了屬性、方法的封裝問題,它的模塊模式直接就融合到語言特性里面了,因此也沒什么模塊模式的說法;然而對于JavaScript這種過于靈活的語言,這種最基本的私有化封裝卻需要用一個設計模式來解決了。
在JavaScript中,“private”是作為保留字,而不是關鍵字的,也就是說,JavaScript沒有私有化這一功能(糾結吧)。解決解決這問題有兩種方法,一是定義變量的時候在前面加上下劃線“_”,也就是告訴其他開發者,不要動這個變量喲;另一種則是利用閉包。第一種方法并不是真正的私有,只是一種規范,如果要做到真正的私有,還是要用第二種方法——閉包。
我們創建一個匿名函數,然后立即運行它,此匿名函數中的所有代碼都存在于一個“閉包”之中,從而得到私有性,并在特定作用域中保持可被訪問。
(function () {
//此作用域的所有變量、函數依舊可在特定作用域中被訪問
})();
var Module = (function () {
var my={},
privateVar = 8;//私有屬性
function privateFun() {//私有方法
return ++privateVar;
};
my.publicVar = 1;//公共屬性
my.moduleFun = function () {//公共方法
return privateFun();
};
return my;
}());
console.log(Module.publicVar);//1
console.log(Module.publicFun());//9
在匿名函數中我們返回了一個my變量給Module作為外部訪問閉包內容的接口,除閉包內my之外的內容都得到了私有性保護,閉包的數據在Module變量的作用域中保持可以訪問。
好了,模塊模式解決了JavaScript私有化的問題,我們可以利用它來定義命名空間、單例、擁有私有化封裝的對象等等。然而模塊模式也并非盡善盡美。例如,我們定義私有、公共變量的方法是不同的,當開發過程中我們需要改變某個變量的可見性的時候,就不得不在它所有出現過的地方進行修改;并且JavaScript作為動態編譯的語言,我們可以隨時給對象添加屬性、方法,然而我們在閉包之外定義的方法是無法直接訪問私有數據的