命名空間有助於減小程序中所須要的全局變量的數量,而且同事還有助於避免命名衝突或過長的名字前綴。咱們能夠建立一個全局對象,將所需的方法,屬性添加到這個對象中。避免了變量全局污染。並且一樣能避免與第三庫的命名衝突。可是一樣存在一些缺點:dom
當咱們往這個全局對象添加一個屬性時,可能覆蓋以前已經定義的屬性了,全部咱們在添加時,先得檢測這個添加的屬性在這個全局對象中是否已經存在。Code:模塊化
var MYAPP={};
if(typeof MYAPP === "undefined"){
var MYAPP={};
}
var MYAPP = MYAPP || {};
複製代碼
這種檢測一個對象好使,可是檢測鏈式對象時,顯得乏力,代碼也會變得臃腫。全部咱們須要設計一個能夠檢測鏈式對象的方法。Code:函數
MYAPP.namespace('MYAPP.modules.module2');
複製代碼
具體的方法實現。Code:測試
var MYAPP = MYAPP || {};
MYAPP.namespace = function (ns_string){
var parts = ns_string.split('.'),
parent = MYAPP,
i;
if(parent[0] === "MYAPP"){
parts = parts.slice(1);
}
for(i=0; i < parts.length; i++>){
if(typeof parts[i] === "undefined"){
parent[parts[i]]={};
}
parent = parent[parts[i]]
}
return parent;
};
複製代碼
在函數或頂部聲明代碼所依賴的模塊是一個很好的方法。由於這種聲明僅涉及建立一個局部變量並使其指向所需的模塊。Code:this
var myFunction = function (){
var event = YAHOO.util.Event,
dom = YAHOO.util.Dom;
};
複製代碼
這種模式有以下幾個優勢:spa
js中並無特殊的語法來表示私有、保護、或公共屬性和方法。由於js中全部對象的成員都是公共的。prototype
好比咱們隨便建立一個對象:設計
var obj{
name:'nei',
run:function(){
console.log('Run');
}
};
obj.name //公共的,能夠隨便訪問的。
複製代碼
即便使用構造函數一樣如此:code
function Obj(){
this.name='Nei';
this.run=function(){
console.log('run');
};
}
var o1=new Obj();
o1.name //公共的 能夠隨便訪問的
複製代碼
可是有時咱們須要私有成員,因此誕生了下面的這些生成私有成員的方法。對象
雖然js自己沒有直接建立私有成員的方法,可是咱們將變量控制在函數做用域內,保證外部訪問不到它,這樣同樣能夠建立私有成員,好比咱們建立一個類,在類裏面建立一個局部變量,而後用公共方法將它暴露出去,這樣咱們就能夠建立一個私有變量,可是有個公共方法又能夠訪問到它。
function Nei(){
var _name='nei';
this.getName=function(){
return _name;
};
}
var n=new Nei();
n.name //undefined
n.getName() //"nei"
複製代碼
模塊模式就以下幾種的集合:
顧名思義就是提供了一個可用於模塊運行的環境,且不會對其餘模塊和我的沙箱形成任何影響。
命名空間模式中有一個全局對象,在沙箱模式中,咱們能夠設置一個全局構造函數,建立一個隔離的沙箱環境。Code:
new Sandbox(function(box)){
....
});
複製代碼
經過添加新特徵,使這個模式更先進:
靜態成員分爲公有靜態成員和私有靜態成員
所謂公有就是直接暴露在對象的屬性上,外部能夠訪問。Code:
var Garget=function(){};
//靜態方法
Garget.isShiny=function(){
return "you bet";
};
//普通方法
Garget.prototype.setPrice=function(price){
this.price=price;
};
//能夠直接調用靜態方法
Garget.isShiny();//輸出 you bet
//普通方法必須建立一個實例,實例調用
var demo1=new Garget();
demo1.setPrice(12);
複製代碼
試圖以靜態方法調用一個實例方法是沒法正常運行的。一樣,若是使用實例調用靜態方法也是沒法正常運行的:
typeof Garget.setPrice; // undefined
typeof demo1.isShiny; // undefined
複製代碼
若是靜態方法也可以被實例調用,只需從新寫一個原型方法便可:
Garget.prototype.isShiny=Garget.isShiny;
demo1.isShiny; // 輸出 「you bet」
複製代碼
可是要注意這裏的this指向問題,執行Garget.isShiny時,this指向Garget。執行demo1.isShiny時,this指向demo1。
咱們能夠用instanceof肯定方法是如何被調用的:
var Garget=function(price){
this.price=price
};
Garget.isShiny=function(){
var msg="you bet";
is(this instanceof Garget){
msg += ", it costs $"+ this.price + "!";
}
return msg;
};
Garget.prototype.isShiny=function(){
return Garget.isShiny.call(this);
};
//調用靜態方法
Garget.isShiny; // 輸出 "you bet"
//實例調用
var d1=new Garget(12);
d1.isShiny(); // 輸出 "you bet,it costs $12!"
複製代碼
私有靜態成員具備以下屬性:
利用當即執行函數實現一個簡單的私有靜態成員:
var Garget=(function(){
var counter=0;
return function(){
console.log(counter+=1);
};
})();
//屢次調用
var d1=new Garget(); // 1
var d2=new Garget(); // 2
var d3=new Garget(); // 3
複製代碼
如今,咱們經過一個特權方法將私有屬性暴露出去:
var Garget=(function(){
var counter=0,
NewGarget;
NewGarget=function(){
counter+=1;
};
//私有特權方法
NewGarget.prototype.getLastId=function(){
return counter;
};
//重寫構造函數
return NewGarget;
})();
//測試
var d1=new Garget();
d1.getLastId(); // 1
var d2=new Garget();
d2.getLastId(); // 2
var d3=new Garget();
d3.getLastId(); // 3
複製代碼
靜態屬性能夠包含非實例相關的方法和數據,而且不會爲每一個實例從新建立靜態屬性。
鏈模式最重要的一個要點,須要顯示返回的this對象。