JavaScript利用閉包實(shí)現(xiàn)模塊化
利用閉包的強(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ì)象字面量語(yǔ)法{ 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í)踐閉包的條件。如果要更簡(jiǎn)單的描述,模塊模式需要具備兩個(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)行簡(jiǎ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è)簡(jiǎn)單但強(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)行修改,包括添加或刪除方法和屬性,以及修改它們的值。
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持腳本之家!
- JS沙箱模式實(shí)例分析
- JavaScript 設(shè)計(jì)模式 安全沙箱模式
- JavaScript的模塊化:封裝(閉包),繼承(原型) 介紹
- JS面向?qū)ο蠡A(chǔ)講解(工廠模式、構(gòu)造函數(shù)模式、原型模式、混合模式、動(dòng)態(tài)原型模式)
- js面向?qū)ο笾R妱?chuàng)建對(duì)象的幾種方式(工廠模式、構(gòu)造函數(shù)模式、原型模式)
- JavaScript設(shè)計(jì)模式之觀察者模式(發(fā)布者-訂閱者模式)
- JavaScript 設(shè)計(jì)模式之組合模式解析
- javascript 設(shè)計(jì)模式之單體模式 面向?qū)ο髮W(xué)習(xí)基礎(chǔ)
- javascript設(shè)計(jì)模式之解釋器模式詳解
- 常用的Javascript設(shè)計(jì)模式小結(jié)
- JavaScript設(shè)計(jì)模式之工廠方法模式介紹
- JS實(shí)現(xiàn)閉包中的沙箱模式示例
相關(guān)文章
使用webpack/gulp構(gòu)建TypeScript項(xiàng)目的方法示例
這篇文章主要介紹了使用webpack/gulp構(gòu)建TypeScript項(xiàng)目的方法示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
JavaScript模擬實(shí)現(xiàn)鍵盤打字效果
這篇文章主要介紹了JavaScript模擬實(shí)現(xiàn)鍵盤打字效果,本文直接給出實(shí)例代碼,需要的朋友可以參考下2015-06-06
JavaScript一文帶你玩轉(zhuǎn)web表單網(wǎng)頁(yè)
表單通常用來收集網(wǎng)頁(yè)訪問者信息,常見的表單比如搜索引擎的搜索框、各網(wǎng)頁(yè)應(yīng)用的注冊(cè)或者登陸界面等,通讀本篇對(duì)大家的學(xué)習(xí)或工作具有一定的價(jià)值,需要的朋友可以參考下2021-10-10
JavaScript canvas實(shí)現(xiàn)刮刮樂案例
這篇文章主要為大家詳細(xì)介紹了JavaScript canvas實(shí)現(xiàn)刮刮樂案例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10
JavaScript實(shí)現(xiàn)可拖拽的拖動(dòng)層Div實(shí)例
這篇文章主要介紹了JavaScript實(shí)現(xiàn)可拖拽的拖動(dòng)層Div的方法,拖拽頁(yè)面中的div塊可實(shí)現(xiàn)div塊按照拖動(dòng)軌跡移動(dòng)的效果,涉及javascript鼠標(biāo)事件、頁(yè)面元素樣式結(jié)合事件函數(shù)動(dòng)態(tài)操作的相關(guān)技巧,需要的朋友可以參考下2015-08-08
JS瀏覽器導(dǎo)航欄navigator的一些冷知識(shí)
這篇文章主要為大家介紹了JS導(dǎo)航欄navigator的一些冷知識(shí)使用方法實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
javascript實(shí)現(xiàn)二叉樹遍歷的代碼
這篇文章主要介紹了javascript實(shí)現(xiàn)二叉樹遍歷的代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06
通過action傳過來的值在option獲取進(jìn)行驗(yàn)證的方法
通過action傳過來的值在option獲取進(jìn)行驗(yàn)證,下面有個(gè)不錯(cuò)的示例,需要的朋友不要錯(cuò)過2013-11-11

