成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

深入了解Javascript模塊化編程

騫諱護 / 2738人閱讀

摘要:我們將簡單地創(chuàng)建一個匿名函數(shù)并立即執(zhí)行它。注意這對包裹匿名函數(shù)的最外層括號。幸運的是,我們的匿名函數(shù)提供了簡單的變通方法。另外,它還維護了一個利用匿名函數(shù)閉包的私有的內(nèi)置狀態(tài)。

  

本文譯自Ben Cherry的《JavaScript Module Pattern: In-Depth》。雖然個人不太認(rèn)同js中私有變量存在的必要性,但是本文非常全面地介紹了Javascript中模塊化模式地方方面面。我讀完之后還是受益匪淺,所以翻譯出來希望對各位也有些幫助。

模塊化編程是一種非常常見Javascript編程模式。它一般來說可以使得代碼更易于理解,但是有許多優(yōu)秀的實踐還沒有廣為人知。在這篇文章中,我將會回顧一下js模塊化編程的基礎(chǔ),并且將會講到一些真的非常值得一提的進(jìn)階話題,包括一個我認(rèn)為是我自創(chuàng)的模式。

基礎(chǔ)

我們首先簡單地概述一下,自從三年前Eric Miraglia(YUI的開發(fā)者)第一次發(fā)表博客描述模塊化模式以來的一些模塊化模式。如果你已經(jīng)對于這些模塊化模式非常熟悉了,大可以直接跳過本節(jié),從“進(jìn)階模式”開始閱讀。

匿名閉包

這是一種讓一切變?yōu)榭赡艿幕窘Y(jié)構(gòu),同時它也是Javascript最棒的特性。我們將簡單地創(chuàng)建一個匿名函數(shù)并立即執(zhí)行它。所有的代碼將跑在這個函數(shù)內(nèi),生存在一個提供私有化的閉包中,它足以使得這些閉包中的變量能夠貫穿我們的應(yīng)用的整個生命周期。

(function () {
    // ... all vars and functions are in this scope only
    // still maintains access to all globals
}());

注意這對包裹匿名函數(shù)的最外層括號。因為Javascript的語言特性,這對括號是必須的。在js中由關(guān)鍵詞function開頭的語句總是會被認(rèn)為是函數(shù)聲明式。把這段代碼包裹在括號中就可以讓解釋器知道這是個函數(shù)表達(dá)式。

全局變量導(dǎo)入

Javascript有一個特性叫做隱式全局變量。無論一個變量名在哪兒被用到了,解釋器會根據(jù)作用域鏈來反向找到這個變量的var聲明語句。如果沒有找到var聲明語句,那么這個變量就會被視為全局變量。如果這個變量用在一句賦值語句中,同時這個變量又不存在時,就會創(chuàng)建出一個全局變量。這意味著在匿名閉包中使用或創(chuàng)建全局變量是很容易的。不幸的是,這會導(dǎo)致寫出的代碼極難維護,因為對于人的直觀感受來說,一眼根本分不清那些是全局的變量。

幸運的是,我們的匿名函數(shù)提供了簡單的變通方法。只要將全局變量作為參數(shù)傳遞到我們的匿名函數(shù)中,就可以得到比隱式全局變量更清晰快速的代碼了。下面是示例:

(function ($, YAHOO) {
    // now have access to globals jQuery (as $) and YAHOO in this code
}(jQuery, YAHOO));
模塊導(dǎo)出

有時你不僅想要使用全局變量,你還想要聲明它們,以供反復(fù)使用。我們可以很容易地通過導(dǎo)出它們來做到這一點——通過匿名函數(shù)的返回值。這樣做將會完成一個基本的模塊化模式雛形,接下來會是一個完整的例子:

var MODULE = (function () {
    var my = {},
        privateVariable = 1;

    function privateMethod() {
        // ...
    }

    my.moduleProperty = 1;
    my.moduleMethod = function () {
        // ...
    };

    return my;
}());

注意我們已經(jīng)聲明了一個叫做MODULE的全局模塊,它擁有2個公有的屬性:一個叫做MODULE.moduleMethod的方法和一個叫做MODULE.moduleProperty的變量。另外,它還維護了一個利用匿名函數(shù)閉包的、私有的內(nèi)置狀態(tài)。同時,我們可以很容易地導(dǎo)入需要的全局變量,并像之前我們所學(xué)到的那樣來使用這個模塊化模式。


進(jìn)階模式

上面一節(jié)所描述的基礎(chǔ)已經(jīng)足以應(yīng)對許多情況,現(xiàn)在我們可以將這個模塊化模式進(jìn)一步的發(fā)展,創(chuàng)建更多強大的、可擴展的結(jié)構(gòu)。讓我們從MODULE模塊開始,一一介紹這些進(jìn)階模式。

放大模式

整個模塊必須在一個文件中是模塊化模式的一個限制。任何一個參與大型項目的人都會明白將js拆分多個文件的價值。幸運的是,我們擁有一個很棒的實現(xiàn)來放大模塊。首先,我們導(dǎo)入一個模塊,并為它添加屬性,最后再導(dǎo)出它。下面是一個例子——從原本的MODULE中放大它:

var MODULE = (function (my) {
    my.anotherMethod = function () {
        // added method...
    };

    return my;
}(MODULE));

我們用var關(guān)鍵詞來保證一致性,雖然它在此處不是必須的。在這段代碼執(zhí)行完之后,我們的模塊就已經(jīng)擁有了一個新的、叫做MODULE.anotherMethod的公有方法。這個放大文件也會維護它自己的私有內(nèi)置狀態(tài)和導(dǎo)入的對象。

寬放大模式

我們的上面例子需要我們的初始化模塊最先被執(zhí)行,然后放大模塊才能執(zhí)行,當(dāng)然有時這可能也不一定是必需的。Javascript應(yīng)用可以做到的、用來提升性能的、最棒的事之一就是異步執(zhí)行腳本。我們可以創(chuàng)建靈活的多部分模塊并通過寬放大模式使它們可以以任意順序加載。每一個文件都需要按下面的結(jié)構(gòu)組織:

var MODULE = (function (my) {
    // add capabilities...

    return my;
}(MODULE || {}));

在這個模式中,var表達(dá)式使必需的。注意如果MODULE還未初始化過,這句導(dǎo)入語句會創(chuàng)建MODULE。這意味著你可以用一個像LABjs的工具來并行加載你所有的模塊文件,而不會被阻塞。

緊放大模式

寬放大模式非常不錯,但它也會給你的模塊帶來一些限制。最重要的是,你不能安全地覆蓋模塊的屬性。你也無法在初始化的時候,使用其他文件中的屬性(但你可以在運行的時候用)。緊放大模式包含了一個加載的順序序列,并且允許覆蓋屬性。這兒是一個簡單的例子(放大我們的原始MODULE):

var MODULE = (function (my) {
    var old_moduleMethod = my.moduleMethod;

    my.moduleMethod = function () {
        // method override, has access to old through old_moduleMethod...
    };

    return my;
}(MODULE));

我們在上面的例子中覆蓋了MODULE.moduleMethod的實現(xiàn),但在需要的時候,可以維護一個對原來方法的引用。

克隆與繼承
var MODULE_TWO = (function (old) {
    var my = {},
        key;

    for (key in old) {
        if (old.hasOwnProperty(key)) {
            my[key] = old[key];
        }
    }

    var super_moduleMethod = old.moduleMethod;
    my.moduleMethod = function () {
        // override method on the clone, access to super through super_moduleMethod
    };

    return my;
}(MODULE));

這個模式可能是最缺乏靈活性的一種選擇了。它確實使得代碼顯得很整潔,但那是用靈活性的代價換來的。正如我上面寫的這段代碼,如果某個屬性是對象或者函數(shù),它將不會被復(fù)制,而是會成為這個對象或函數(shù)的第二個引用。修改了其中的某一個就會同時修改另一個(譯者注:因為它們根本就是一個?。。?。這可以通過遞歸克隆過程來解決這個對象克隆問題,但函數(shù)克隆可能無法解決,也許用eval可以解決吧。因此,我在這篇文章中講述這個方法僅僅是考慮到文章的完整性。

跨文件私有變量

把一個模塊分到多個文件中有一個重大的限制:每一個文件都維護了各自的私有變量,并且無法訪問到其他文件的私有變量。但這個問題是可以解決的。這里有一個維護跨文件私有變量的、寬放大模塊的例子:

var MODULE = (function (my) {
    var _private = my._private = my._private || {},
        _seal = my._seal = my._seal || function () {
            delete my._private;
            delete my._seal;
            delete my._unseal;
        },
        _unseal = my._unseal = my._unseal || function () {
            my._private = _private;
            my._seal = _seal;
            my._unseal = _unseal;
        };

    // permanent access to _private, _seal, and _unseal

    return my;
}(MODULE || {}));

所有文件可以在它們各自的_private變量上設(shè)置屬性,并且它理解可以被其他文件訪問。一旦這個模塊加載完成,應(yīng)用程序可以調(diào)用MODULE._seal()來防止外部對內(nèi)部_private的調(diào)用。如果這個模塊需要被重新放大,在任何一個文件中的內(nèi)部方法可以在加載新的文件前調(diào)用_unseal(),并在新文件執(zhí)行好以后再次調(diào)用_seal()。我如今在工作中使用這種模式,而且我在其他地方還沒有見過這種方法。我覺得這是一種非常有用的模式,很值得就這個模式本身寫一篇文章。

子模塊

我們的最后一種進(jìn)階模式是顯而易見最簡單的。創(chuàng)建子模塊有許多優(yōu)秀的實例。這就像是創(chuàng)建一般的模塊一樣:

MODULE.sub = (function () {
    var my = {};
    // ...

    return my;
}());

雖然這看上去很簡單,但我覺得還是值得在這里提一提。子模塊擁有一切一般模塊的進(jìn)階優(yōu)勢,包括了放大模式和私有化狀態(tài)。


結(jié)論

大多數(shù)進(jìn)階模式可以結(jié)合到一起來創(chuàng)建一個更為有用的模式。如果實在要我推薦一種設(shè)計復(fù)雜應(yīng)用程序的模塊化模式的化,我會選擇結(jié)合寬放大模式、私有變量和子模塊。

我還未考慮過這些模式的性能問題,但我寧愿把這轉(zhuǎn)化為一個更簡單的思考方式:如果一個模塊化模式有很好的性能,那么它能夠把最小化做的很棒,使得下載這個腳本文件更快。使用寬放大模式可以允許簡單的非阻塞并行下載,這就會加快下載速度。初始化時間可能會稍慢于其他方法,但權(quán)衡利弊后這還是值得的。只要全局變量導(dǎo)入準(zhǔn)確,運行時性能應(yīng)該會不會受到影響,而且還有可能在子模塊中通過用私有變量縮短引用鏈來得到更快的運行速度。

作為結(jié)束,這里是一個子模塊動態(tài)地把自身加載到它的父模塊的例子(如果父模塊不存在則創(chuàng)建它)。為了簡潔,我把私有變量給去除了,當(dāng)然加上私有變量也是很簡單的啦。這種編程模式允許一整個復(fù)雜層級結(jié)構(gòu)代碼庫通過子模塊并行地完成加載。

var UTIL = (function (parent, $) {
    var my = parent.ajax = parent.ajax || {};

    my.get = function (url, params, callback) {
        // ok, so I"m cheating a bit :)
        return $.getJSON(url, params, callback);
    };

    // etc...

    return parent;
}(UTIL || {}, jQuery));

我希望這篇文章對你有幫助,請在文章下面留言分享你的想法。從現(xiàn)在起,就開始寫更棒、更模塊化的Javascript吧!

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/78165.html

相關(guān)文章

  • ES6-7

    摘要:的翻譯文檔由的維護很多人說,阮老師已經(jīng)有一本關(guān)于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(中文版) 超詳細(xì)介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...

    mudiyouyou 評論0 收藏0
  • javascript知識點

    摘要:模塊化是隨著前端技術(shù)的發(fā)展,前端代碼爆炸式增長后,工程化所采取的必然措施。目前模塊化的思想分為和。特別指出,事件不等同于異步,回調(diào)也不等同于異步。將會討論安全的類型檢測惰性載入函數(shù)凍結(jié)對象定時器等話題。 Vue.js 前后端同構(gòu)方案之準(zhǔn)備篇——代碼優(yōu)化 目前 Vue.js 的火爆不亞于當(dāng)初的 React,本人對寫代碼有潔癖,代碼也是藝術(shù)。此篇是準(zhǔn)備篇,工欲善其事,必先利其器。我們先在代...

    Karrdy 評論0 收藏0
  • 雙十二大前端工程師讀書清單

    摘要:本文最早為雙十一而作,原標(biāo)題雙大前端工程師讀書清單,以付費的形式發(fā)布在上。發(fā)布完本次預(yù)告后,捕捉到了一個友善的吐槽讀書清單也要收費。這本書便從的異步編程講起,幫助我們設(shè)計快速響應(yīng)的網(wǎng)絡(luò)應(yīng)用,而非簡單的頁面。 本文最早為雙十一而作,原標(biāo)題雙 11 大前端工程師讀書清單,以付費的形式發(fā)布在 GitChat 上。發(fā)布之后在讀者圈群聊中和讀者進(jìn)行了深入的交流,現(xiàn)免費分享到這里,不足之處歡迎指教...

    happen 評論0 收藏0
  • 雙十二大前端工程師讀書清單

    摘要:本文最早為雙十一而作,原標(biāo)題雙大前端工程師讀書清單,以付費的形式發(fā)布在上。發(fā)布完本次預(yù)告后,捕捉到了一個友善的吐槽讀書清單也要收費。這本書便從的異步編程講起,幫助我們設(shè)計快速響應(yīng)的網(wǎng)絡(luò)應(yīng)用,而非簡單的頁面。 本文最早為雙十一而作,原標(biāo)題雙 11 大前端工程師讀書清單,以付費的形式發(fā)布在 GitChat 上。發(fā)布之后在讀者圈群聊中和讀者進(jìn)行了深入的交流,現(xiàn)免費分享到這里,不足之處歡迎指教...

    余學(xué)文 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<