單體是一個用來劃分命名空間並將一些相關的屬性與方法組織在一起的對象,如果她可以被實例化的話,那她只能被實例化一次(她只能嫁一次,不能二婚)。
單體模式是javascript裡面最基本但也是最有用的模式之一。
特點:
1. 可以用來劃分命名空間,從而清除全局變量所帶來的危險或影響。
2. 利用分支技術來來封裝浏覽器之間的差異。
3. 可以把代碼組織的更為一體,便於閱讀和維護。
單體模式的基本寫法:
/* 最基本的單體模式 */ var her = { name: 'Anna', sex: 'women', say: function(){ // 一些處理邏輯...... }, doing: function(){ // 另一些處理函數...... } }
1. 劃分命名空間:
var box = { width: 0, height: 0, getArea: function(){ return this.width * this.width; // js中對象成的訪問必須是顯示的,即this是不能省略的 }, init: function(w, h){ // width = w; // height = h;這種方式相當於定義了兩個全局變量,(沒加var聲明的變量為全局變量) // 並不是對對象width和height的賦值 // 下面是正確的 this.width = w; this.height = h; } } //box劃分了一個命名空間,命名空間裡的變量只在空間裡有效
上面的單體中的所有的成員以及方法都是公有的(public),也就是在單體的外部可以對她們進行任意的改動(但不能訪問其中的局部變量),那為什麼說單體提供了一個命名空間呢?
別急,我們接著往下看:
var box = { width:0, height:0,//單體的變量 getArea:function(){ return width * height;// width,height其實並不是單體的變量,而是在init中定義的全局變量 } init:function(w,h){ width = w; height = h; } }// init中width,height其實並不是單體的變量 window.onload = function(){ var init = box.getArea(); alert(init); }
由於沒有對init中的width,height進行初始化,所以會報錯,這樣改一下:
var box = { width:0, height:0, getArea:function(){ return width * height; }, init:function(w,h){ width = w; height = h; } } window.onload = function(){ width = 0; height = 0; //or box.init(0,0); var init = box.getArea(); alert(init); }
發現可以了,由於init和 getArea所用的width和height並不是歸單體所有的變量,而是一個全局變量,所以我們可以在單體外面進行隨意調用而不受影響、
var box = { width: 0, height: 0, getArea: function(){ return width * height;//js中對象成的訪問必須是顯示的,即this是不能省略的 }, init:function(w,h){ width = w; height = h; } }//這裡的width,height其實並不是單體的對象 window.onload = function(){ width = 0; height = 0; var width = box.getArea(); alert(width); }
這樣寫又會報錯了,可見我們以上的方式對於全局變量並沒有建立起一個命名空間,全局變量為我們帶來了危險。所以最上面的寫法是對的,我們來驗證一下:
var box = { width: 2, height: 2, getArea: function(){ return this.width * this.height;/ /js中對象成的訪問必須是顯示的,即this是不能省略的 }, init:function(w,h){ this.width = w; this.height = h; } } window.onload = function(){ width = 0; // 不會影響單體中的局部變量也就是命名空間 height = 0; // 不會影響單體中的局部變量也就是命名空間 var width = box.getArea(); alert(width); }
可見在window.onload中的width 和height已經沒有干擾了,因為單體為單體中的width和height建立了一個命名空間。
2. 成員的屬性:
雖然在javascript中沒有這麼嚴格的面向對象(oop),但是我們可以借助閉包來進行一個模仿,畢竟有的變量設為public是很不好的。
var her = (function(){ var name = 'Anna'; var sex = 'women'; return { getArea: function(){ return name + 'is a' + sex; }, init:function(b){ name = b; } } })(); window.onload = function(){ her.name = 'Jock'; // 無法訪問 alert(ger.getArea()); her.init('Lous'); alert(her.getArea()); }
私有變量、方法是只讀的,公有變量、方法是可讀可寫的。
訪問:
對於私有成員,直接訪問即可,前面不用加任何修飾,
對於公有的訪問在單體作用域內前面要加上“this.”,在單體作用域外前面要加上“her.”(單體名字.)
3.利用分支技術來來封裝浏覽器之間的差異
注意的地方:
a. 一定要用閉包,實現即時綁定
b. 每個分支之間用分號隔開
c. 最後返回的是分支的名字
d. 調用的時候用單體名+分支的方法名;
// 利用單體的分支技術來定義XHR(XMLHttpRequest)對象,必須要用閉包才可以實現 var XHR = (function(){ //The three branches var standard = { cXHR:function(){ return new XMLHttpRequest(); } }; var activeXNew = { cXHR:function(){ return new ActiveXObject('Msxml2.XMLHttp'); } }; var activeXOld = { cXHR:function(){ return new ActiveXObject('Microsoft.XMLHttp'); } }; //To assign(分配) the branch, try each method;return whatever doesn't fail var testObject; try{ testObject = standard.cXHR(); return standard;// return this branch if no error was thrown }catch(e){ try{ testObject = activeXNew.cXHR(); return activeXNew; }catch(e){ try{ testObject = activeXOld.cXHR(); return activeXOld; }catch(e){ throw new Error('Create the XMLHttpRequestObject failed!'); } } } })(); window.onload = function(){ alert(XHR.cXHR()); }
以上所述是小編給大家介紹的JavaScript設計模式之單體模式全面解析,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對網站的支持!