近期買到手了一本《javascript架構設計》,具體介紹開發js架構所用到的知識。初讀一點,樂帝脆弱的理論修養就暴露無遺了,是以專門加強理論修養,重看javascript程式設計模式的舉例。以下來介紹下js中,常見的程式設計模式。
1.命名空間
同其它進階語言一樣,js中的命名空間概念,也是為了降低命名沖突,但js沒有命名空間keyword。js實作命名空間的思路是定義一個全局變量,将此命名空間的變量和方法,定義為這個全局變量的屬性。
var MYAPP=MYAPP||{};//全局變量
MYAPP.dom={};//全局變量下的對象
MYAPP.dom.Element=function(type,prop){
var tmp=document.createElement(type);
for(var i in prop)
{
tmp.setAttribute(i,prop[i]);
}
return tmp;
}
MYAPP.dom.Text=function(txt){
return document.createTextNode(txt);
}//兩個全局變量下對象的方法,這樣寫降低了全局變量的使用,降低了命名沖突,達到了命名空間的效果
var e11=new MYAPP.dom.Element("a",{href:"www.baidu.com"});
var e12=new MYAPP.dom.Text('click me');
e11.appendChild(e12);
document.body.appendChild(e11);
namespace函數,用于定義命名空間。
var MYAPP={};
MYAPP.namespace=function(name){
var parts=name.split('.');
current=MYAPP;
for(var i in parts)
{
if(!current[parts[i]])
{
current[parts[i]]={};//依次對屬性設定成對象
}
curent=current[parts[i]];//并将每一個對象都添為鍊式的前一個對象的屬性
}
return current;
}
MYAPP.namespace('dom.style')
2.初始化分支和延遲定義模式
這兩個模式不同之處,能夠從js架構設計角度考慮。構造一個架構,有些子產品必須初始化的,比方jquery的$符号,另外一些僅僅有被調用到才須要初始化操作。這種優點在于,保證了架構的可用性和載入效率上的最優化。
初始化模式:
/初始化分支
var MYAPP={};
MYAPP.event={
addListener:null,
removeListener:null
};
if(typeof window.addEventListener==='function'){
MYAPP.event.addListener=function(e1,type,fn){
e1.addEventListener(type,fn,false);
};
MYAPP.event.removeListener=function(e1,type,fn){
e1.removeEventListener(type,fn,false);
};
}else if(typeof document.attachEvent==='function'){
MYAPP.event.addListener=function(e1,type,fn){
e1.attachEvent('on'+type,fn);
};
MYAPP.event.removeListener=function(e1,type,fn){
e1.deleteEvent('on'+type,fn);
};
}else{
MYAPP.event.addListener=function(e1,type,fn){
e1['on'+type]=fn;
};
MYAPP.event.removeListener=function(e1,type,fn){
e1['on'+type]=null;
};
}//載入腳本時運作分支,在子產品初始化過程中就将部分代碼進行處理,有利于提高效率
延遲定義模式:
//延遲定義 相對于初始化分支,延遲定義模式中,某些函數可能永遠不會被調用
//延遲模式會使初始化過程更輕量
var MYAPP={};
MYAPP.event={
addListener:function(e1,type,fn){
if(typeof e1.addEventListener==='function'){
MYAPP.event.addListener=function(e1,type,fn){
e1.addEventListener(type,fn,false);
};
}else if(typeof e1.attachEvent==='function'){
MYAPP.event.addListener=function(e1,type,fn){
e1.attachEvent('on'+type,fn);
};
}else{
MYAPP.event.addListener=function(e1,type,fn){
e1['on'+type]=fn;
};
}
MYAPP.event.addListener(e1,type,fn);
}
};//延遲定義的意義在于,假設用到就會初始化事件,不用就不會執行多餘代碼
3.配置對象的模式
配置對象的模式,用于處理函數中有非常多個參數和方法的問題。用對象來替代多個參數,即讓這些參數都成為對象某一屬性。優勢在于:不用考慮參數的順序、跳過某些參數設定、擴充性和可讀性更強。
//配置對象
var MYAPP={};
MYAPP.dom={};
MYAPP.dom.Button=function(text,conf){//用配置對象作為函數參數,有利于解決函數參數順序問題,而且能夠跳過一些參數
var b=document.createElement('input');
b.type=config.type||'submit';
b.value=text;
b.font=conf.font||'Verdana';
return b;
}
var config={
font:'Arial,Verdana,sanf-serif',
color:'white'
}//配置對象,可讀性好,擴充性好,可依據須要随時改動配置對象
document.body.appendChild(new MYAPP.dom.Button('puuush',config));
4.私有函數公有化與自運作函數模式
對象中私有函數對外不可見,私有函數公有化模式,用到了自運作函數的模式,傳回一個對象,保有對自由函數可訪問性。
//私有函數公有化與自運作函數
var MYAPP={};
MYAPP.dom=(function(){
var _setStyle=function(e1,prop,value){
console.log('setSTyle');
};
var _getStyle=function(e1,prop){
console.log('getStyle');
};
return{
setStyle:_setStyle,
getStyle:_getStyle,
yetAnther:_setStyle
};
})();//通過傳回對象屬性保留對私有函數的訪問權限
//此種方法也是用自運作函數的方法使用方法
5.鍊式調用模式
//鍊式調用模式
var obj=new MYAPP.dome.Element('span');
obj.setText('hello,world').setStyle('color','red');
//讓setText()方法傳回this就能夠實作鍊式調用了