起因
在JavaScript發(fā)展初期就是為了實(shí)現(xiàn)簡單的頁面交互邏輯,寥寥數(shù)語即可;如今CPU荣回、瀏覽器性能得到了極大的提升,很多頁面邏輯遷移到了客戶端(表單驗(yàn)證等)叠赦,隨著web2.0時(shí)代的到來驹马,Ajax技術(shù)得到廣泛應(yīng)用革砸,jQuery等前端庫層出不窮除秀,前端代碼日益膨脹
這時(shí)候JavaScript作為嵌入式的腳本語言的定位動(dòng)搖了,JavaScript卻沒有為組織代碼提供任何明顯幫助算利,甚至沒有類的概念册踩,更不用說模塊(module)了,JavaScript極其簡單的代碼組織規(guī)范不足以駕馭如此龐大規(guī)模的代碼
模塊
既然JavaScript不能handle如此大規(guī)模的代碼效拭,我們可以借鑒一下其它語言是怎么處理大規(guī)模程序設(shè)計(jì)的暂吉,在Java中有一個(gè)重要的概念——package,邏輯上相關(guān)的代碼組織到同一個(gè)包內(nèi)缎患,包內(nèi)是一個(gè)相對(duì)獨(dú)立的王國慕的,不用擔(dān)心命名沖突什么的,那么外部如果使用呢挤渔?直接import對(duì)應(yīng)的package即可
import java.util.ArrayList;
遺憾的是JavaScript在設(shè)計(jì)時(shí)定位原因肮街,沒有提供類似的功能,開發(fā)者需要模擬出類似的功能判导,來隔離嫉父、組織復(fù)雜的JavaScript代碼沛硅,我們稱為模塊化。
一個(gè)模塊就是實(shí)現(xiàn)特定功能的文件绕辖,有了模塊摇肌,我們就可以更方便地使用別人的代碼,想要什么功能仪际,就加載什么模塊围小。模塊開發(fā)需要遵循一定的規(guī)范,各行其是就都亂套了
規(guī)范形成的過程是痛苦的弟头,前端的先驅(qū)在刀耕火種吩抓、茹毛飲血的階段開始,發(fā)展到現(xiàn)在初具規(guī)模赴恨,簡單了解一下這段不凡的歷程
函數(shù)封裝
我們?cè)谥v函數(shù)的時(shí)候提到疹娶,函數(shù)一個(gè)功能就是實(shí)現(xiàn)特定邏輯的一組語句打包,而且JavaScript的作用域就是基于函數(shù)的伦连,所以把函數(shù)作為模塊化的第一步是很自然的事情雨饺,在一個(gè)文件里面編寫幾個(gè)相關(guān)函數(shù)就是最開始的模塊了
function fn1(){
statement
}
function fn2(){
statement
}
這樣在需要的以后加載函數(shù)所在文件,調(diào)用函數(shù)就可以了
這種做法的缺點(diǎn)很明顯:污染了全局變量惑淳,無法保證不與其他模塊發(fā)生變量名沖突额港,而且模塊成員之間沒什么關(guān)系
對(duì)象
為了解決上面問題,對(duì)象的寫法應(yīng)運(yùn)而生歧焦,可以把所有的模塊成員封裝在一個(gè)對(duì)象中
var myModule = {
var1: 1,
var2: 2,
fn1: function(){
},
fn2: function(){
}
}
這樣我們?cè)谙M{(diào)用模塊的時(shí)候引用對(duì)應(yīng)文件移斩,然后
myModule.fn2();
這樣避免了變量污染,只要保證模塊名唯一即可绢馍,同時(shí)同一模塊內(nèi)的成員也有了關(guān)系
看似不錯(cuò)的解決方案向瓷,但是也有缺陷,外部可以隨意修改內(nèi)部成員
myModel.var1 = 100;
這樣就會(huì)產(chǎn)生意外的安全問題
立即執(zhí)行函數(shù)
可以通過立即執(zhí)行函數(shù)舰涌,來達(dá)到隱藏細(xì)節(jié)的目的
var myModule = (function(){
var var1 = 1;
var var2 = 2;
function fn1(){
}
function fn2(){
}
return {
fn1: fn1,
fn2: fn2
};
})();
這樣在模塊外部無法修改我們沒有暴露出來的變量猖任、函數(shù)
目前,通行的JavaScript模塊規(guī)范主要有兩種:CommonJS和AMD