本篇文章為大家展示了如何在JavaScript中實(shí)現(xiàn)一個(gè)模塊化功能,內(nèi)容簡明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
“專業(yè)、務(wù)實(shí)、高效、創(chuàng)新、把客戶的事當(dāng)成自己的事”是我們每一個(gè)人一直以來堅(jiān)持追求的企業(yè)文化。 創(chuàng)新互聯(lián)是您可以信賴的網(wǎng)站建設(shè)服務(wù)商、專業(yè)的互聯(lián)網(wǎng)服務(wù)提供商! 專注于網(wǎng)站設(shè)計(jì)制作、網(wǎng)站制作、軟件開發(fā)、設(shè)計(jì)服務(wù)業(yè)務(wù)。我們始終堅(jiān)持以客戶需求為導(dǎo)向,結(jié)合用戶體驗(yàn)與視覺傳達(dá),提供有針對(duì)性的項(xiàng)目解決方案,提供專業(yè)性的建議,創(chuàng)新互聯(lián)建站將不斷地超越自我,追逐市場,引領(lǐng)市場!
利用閉包的強(qiáng)大威力,但從表面上看,它們似乎與回調(diào)無關(guān)。下面一起來研究其中最強(qiáng)大的一個(gè):模塊。
function foo() { var something = "cool"; var another = [1, 2, 3]; function doSomething() { console.log( something ); } function doAnother() { console.log( another.join( " ! " ) ); } }
正如在這段代碼中所看到的,這里并沒有明顯的閉包,只有兩個(gè)私有數(shù)據(jù)變量something和another,以及doSomething() 和doAnother() 兩個(gè)內(nèi)部函數(shù),它們的詞法作用域(而這就是閉包)也就是foo() 的內(nèi)部作用域。
接下來考慮以下代碼:
function CoolModule() { var something = "cool"; var another = [1, 2, 3]; function doSomething() { alert( something ); } function doAnother() { alert( another.join( " ! " ) ); } return { doSomething: doSomething, doAnother: doAnother }; } var foo = CoolModule(); foo.doSomething(); // cool foo.doAnother(); // 1 ! 2 ! 3
這個(gè)模式在JavaScript 中被稱為模塊。最常見的實(shí)現(xiàn)模塊模式的方法通常被稱為模塊暴露,這里展示的是其變體。我們仔細(xì)研究一下這些代碼。
首先,CoolModule() 只是一個(gè)函數(shù),必須要通過調(diào)用它來創(chuàng)建一個(gè)模塊實(shí)例。如果不執(zhí)行外部函數(shù),內(nèi)部作用域和閉包都無法被創(chuàng)建。其次,CoolModule() 返回一個(gè)用對(duì)象字面量語法{ key: value, ... } 來表示的對(duì)象。這個(gè)返回的對(duì)象中含有對(duì)內(nèi)部函數(shù)而不是內(nèi)部數(shù)據(jù)變量的引用。我們保持內(nèi)部數(shù)據(jù)變量是隱藏且私有的狀態(tài)??梢詫⑦@個(gè)對(duì)象類型的返回值看作本質(zhì)上是模塊的公共API。這個(gè)對(duì)象類型的返回值最終被賦值給外部的變量foo,然后就可以通過它來訪問API 中的屬性方法,比如foo.doSomething()。
從模塊中返回一個(gè)實(shí)際的對(duì)象并不是必須的,也可以直接返回一個(gè)內(nèi)部函數(shù)。jQuery 就是一個(gè)很好的例子。jQuery 和$ 標(biāo)識(shí)符就是jQuery 模塊的公共API,但它們本身都是函數(shù)(由于函數(shù)也是對(duì)象,它們本身也可以擁有屬性)。
doSomething() 和doAnother() 函數(shù)具有涵蓋模塊實(shí)例內(nèi)部作用域的閉包( 通過調(diào)用CoolModule() 實(shí)現(xiàn))。當(dāng)通過返回一個(gè)含有屬性引用的對(duì)象的方式來將函數(shù)傳遞到詞法作用域外部時(shí),我們已經(jīng)創(chuàng)造了可以觀察和實(shí)踐閉包的條件。如果要更簡單的描述,模塊模式需要具備兩個(gè)必要條件。
1. 必須有外部的封閉函數(shù),該函數(shù)必須至少被調(diào)用一次(每次調(diào)用都會(huì)創(chuàng)建一個(gè)新的模塊實(shí)例)。
2. 封閉函數(shù)必須返回至少一個(gè)內(nèi)部函數(shù),這樣內(nèi)部函數(shù)才能在私有作用域中形成閉包,并且可以訪問或者修改私有的狀態(tài)。
一個(gè)具有函數(shù)屬性的對(duì)象本身并不是真正的模塊。從方便觀察的角度看,一個(gè)從函數(shù)調(diào)用所返回的,只有數(shù)據(jù)屬性而沒有閉包函數(shù)的對(duì)象并不是真正的模塊。上一個(gè)示例代碼中有一個(gè)叫作CoolModule() 的獨(dú)立的模塊創(chuàng)建器,可以被調(diào)用任意多次,每次調(diào)用都會(huì)創(chuàng)建一個(gè)新的模塊實(shí)例。當(dāng)只需要一個(gè)實(shí)例時(shí),可以對(duì)這個(gè)模式進(jìn)行簡單的改進(jìn)來實(shí)現(xiàn)單例模式:
var foo = (function CoolModule() { var something = "cool"; var another = [1, 2, 3]; function doSomething() { alert( something ); } function doAnother() { alert( another.join( " ! " ) ); } return { doSomething: doSomething, doAnother: doAnother }; })(); foo.doSomething(); // cool foo.doAnother(); // 1 ! 2 ! 3
立即調(diào)用這個(gè)函數(shù)并將返回值直接賦值給單例的模塊實(shí)例標(biāo)識(shí)符foo。
模塊也是普通的函數(shù),因此可以接受參數(shù):
function CoolModule(id) { function identify() { console.log( id ); } return { identify: identify }; } var foo1 = CoolModule( "foo 1" ); var foo2 = CoolModule( "foo 2" ); foo1.identify(); // "foo 1" foo2.identify(); // "foo 2"
模塊模式另一個(gè)簡單但強(qiáng)大的變化用法是,命名將要作為公共API 返回的對(duì)象:
var foo = (function CoolModule(id) { function change() { // 修改公共API publicAPI.identify = identify2; } function identify1() { alert( id ); } function identify2() { alert( id.toUpperCase() ); } var publicAPI = { change: change, identify: identify1 }; return publicAPI; })( "foo module" ); foo.identify(); // foo module foo.change(); foo.identify(); // FOO MODULE
通過在模塊實(shí)例的內(nèi)部保留對(duì)公共API 對(duì)象的內(nèi)部引用,可以從內(nèi)部對(duì)模塊實(shí)例進(jìn)行修改,包括添加或刪除方法和屬性,以及修改它們的值。
上述內(nèi)容就是如何在JavaScript中實(shí)現(xiàn)一個(gè)模塊化功能,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。