亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > JavaScript > 正文

Javascript模塊化編程詳解

2024-05-06 16:11:13
字體:
來源:轉載
供稿:網友
在這篇文章中,我將會回顧一下js模塊化編程的基礎,并且將會講到一些真的非常值得一提的進階話題,包括一個我認為是我自創的模式。
 
 

模塊化編程是一種非常常見Javascript編程模式。它一般來說可以使得代碼更易于理解,但是有許多優秀的實踐還沒有廣為人知。

基礎

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

匿名閉包

這是一種讓一切變為可能的基本結構,同時它也是Javascript最棒的特性。我們將簡單地創建一個匿名函數并立即執行它。所有的代碼將跑在這個函數內,生存在一個提供私有化的閉包中,它足以使得這些閉包中的變量能夠貫穿我們的應用的整個生命周期。

 

復制代碼代碼如下:

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

 

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

全局變量導入

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

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

 

復制代碼代碼如下:

(function ($, YAHOO) {
    // now have access to globals jQuery (as $) and YAHOO in this code
}(jQuery, YAHOO));

 

模塊導出

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

 

復制代碼代碼如下:

var MODULE = (function () {
    var my = {},
        privateVariable = 1;
    function privateMethod() {
        // ...
    }
    my.moduleProperty = 1;
    my.moduleMethod = function () {
        // ...
    };
    return my;
}());

 

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

進階模式

上面一節所描述的基礎已經足以應對許多情況,現在我們可以將這個模塊化模式進一步的發展,創建更多強大的、可擴展的結構。讓我們從MODULE模塊開始,一一介紹這些進階模式。

放大模式

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

 

復制代碼代碼如下:

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

 

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

寬放大模式

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

 

復制代碼代碼如下:

var MODULE = (function (my) {
    // add capabilities...
    return my;
}(MODULE || {}));

 

在這個模式中,var表達式使必需的。注意如果MODULE還未初始化過,這句導入語句會創建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的實現,但在需要的時候,可以維護一個對原來方法的引用。

克隆與繼承

 

復制代碼代碼如下:

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));

 

這個模式可能是最缺乏靈活性的一種選擇了。它確實使得代碼顯得很整潔,但那是用靈活性的代價換來的。正如我上面寫的這段代碼,如果某個屬性是對象或者函數,它將不會被復制,而是會成為這個對象或函數的第二個引用。修改了其中的某一個就會同時修改另一個(譯者注:因為它們根本就是一個?。。?。這可以通過遞歸克隆過程來解決這個對象克隆問題,但函數克隆可能無法解決,也許用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變量上設置屬性,并且它理解可以被其他文件訪問。一旦這個模塊加載完成,應用程序可以調用MODULE._seal()來防止外部對內部_private的調用。如果這個模塊需要被重新放大,在任何一個文件中的內部方法可以在加載新的文件前調用_unseal(),并在新文件執行好以后再次調用_seal()。我如今在工作中使用這種模式,而且我在其他地方還沒有見過這種方法。我覺得這是一種非常有用的模式,很值得就這個模式本身寫一篇文章。

子模塊

我們的最后一種進階模式是顯而易見最簡單的。創建子模塊有許多優秀的實例。這就像是創建一般的模塊一樣:

 

復制代碼代碼如下:

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

 

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

結論

大多數進階模式可以結合到一起來創建一個更為有用的模式。如果實在要我推薦一種設計復雜應用程序的模塊化模式的化,我會選擇結合寬放大模式、私有變量和子模塊。

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

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

 

復制代碼代碼如下:

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));

 

本文總結了當前"Javascript模塊化編程"的最佳實踐,說明如何投入實用。雖然這不是初級教程,但是只要稍稍了解Javascript的基本語法,就能看懂。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
成人免费激情视频| 久久亚洲精品小早川怜子66| 欧美精品videossex88| 92版电视剧仙鹤神针在线观看| 国产成人福利网站| 亚洲va国产va天堂va久久| 国产精品h在线观看| 色婷婷亚洲mv天堂mv在影片| 欧美日韩国产专区| 成人免费观看网址| 亚洲国产另类 国产精品国产免费| 97精品国产97久久久久久免费| 亚洲国产精品电影在线观看| 国产精品久久999| 日韩精品免费在线视频观看| 久久伊人精品一区二区三区| 欧洲s码亚洲m码精品一区| 国产成人午夜视频网址| 亚洲国产中文字幕久久网| 国产精品中文字幕在线| 亚洲精品国产成人| 亚洲福利视频网| 国产成人精品在线视频| 亚洲男人天堂网站| 中文字幕亚洲图片| 另类少妇人与禽zozz0性伦| 国产欧美一区二区三区在线| 视频在线观看99| 久久影院中文字幕| 亚洲成人性视频| 欧美色图在线视频| 亚洲自拍偷拍第一页| 国产一区二区动漫| 国产精品视频99| 国产在线观看一区二区三区| 日韩精品在线影院| 国产精品劲爆视频| 日韩一二三在线视频播| 久久91亚洲精品中文字幕奶水| 欧美激情欧美狂野欧美精品| 97免费视频在线播放| 88国产精品欧美一区二区三区| 136fldh精品导航福利| 国产精品99久久久久久www| 欧美黄色三级网站| 欧美日韩美女在线观看| 成人午夜在线观看| 美女黄色丝袜一区| 欧美成人国产va精品日本一级| 欧美大片大片在线播放| 亚洲欧美日韩国产中文专区| 欧美精品在线网站| 欧美精品一二区| 日韩中文字幕在线精品| 欧美亚洲国产日韩2020| www亚洲欧美| 久久理论片午夜琪琪电影网| 国产在线视频2019最新视频| 在线播放日韩欧美| 欧美综合国产精品久久丁香| 久久成人18免费网站| 精品国产成人av| 在线视频国产日韩| 亚洲图中文字幕| 国产精品444| 日韩成人在线观看| 亚洲国产精品成人一区二区| 全亚洲最色的网站在线观看| 亚洲欧美视频在线| 人人爽久久涩噜噜噜网站| 欧美在线视频观看免费网站| 精品中文字幕在线2019| 国产精品久久久久久久久粉嫩av| 国产成人精品免高潮在线观看| 国产视频精品一区二区三区| 中文字幕成人在线| 精品国产乱码久久久久久婷婷| 亚洲女人天堂视频| 国产精品麻豆va在线播放| 狠狠色狠狠色综合日日小说| 精品久久久在线观看| 在线观看久久久久久| 亚洲欧洲一区二区三区在线观看| 日韩av在线网址| 国产精品视频资源| 国产精品日日摸夜夜添夜夜av| 亚洲人成网站777色婷婷| 国产不卡一区二区在线播放| 亚洲综合中文字幕68页| 亚洲国产欧美一区二区三区久久| 欧美另类在线播放| 日韩欧美国产网站| 日韩免费观看在线观看| 成人女保姆的销魂服务| 亚洲精品国产精品久久清纯直播| 午夜精品一区二区三区在线| 亚洲国产古装精品网站| 国产自产女人91一区在线观看| 91网站在线看| 国产成人午夜视频网址| 亚洲女人天堂成人av在线| 欧美激情一级精品国产| 日韩av大片在线| 国产偷国产偷亚洲清高网站| 久久伊人色综合| 亚洲第一精品夜夜躁人人爽| 国产成人精品免高潮费视频| 久久久久久久91| 国产视频欧美视频| 亚洲男人第一av网站| 欧美激情xxxx性bbbb| 亚洲成人av在线播放| 国产欧美韩国高清| 国产主播精品在线| 91精品国产亚洲| 亚洲热线99精品视频| 亚洲国产另类久久精品| 欧美大人香蕉在线| 日韩精品免费观看| 亚洲精品美女免费| 久久久久久久久久av| 国产精品白嫩初高中害羞小美女| 国产精品永久免费视频| 国产精品video| 97av在线视频| 国产亚洲视频在线观看| 日韩免费看的电影电视剧大全| 国产精品午夜国产小视频| 国产精品亚洲аv天堂网| 久久午夜a级毛片| 精品久久久久久久久久国产| 久久99精品久久久久久青青91| 视频一区视频二区国产精品| 亚洲毛片在线看| 国产精品香蕉在线观看| 精品视频在线观看日韩| 91青草视频久久| 日韩视频在线免费观看| 成人中文字幕在线观看| 欧美在线视频观看免费网站| 亚洲成人国产精品| 欧美视频精品一区| 日韩亚洲精品电影| 亚洲国语精品自产拍在线观看| 91久久精品国产91性色| 97福利一区二区| 成人黄色免费看| 欧美国产视频日韩| 亚洲精品www久久久久久广东| 国产精品看片资源| 久久精品视频在线| 久久天堂电影网| 日韩一区二区三区xxxx| 日韩中文字幕在线播放| 亚洲伊人一本大道中文字幕| 国模精品系列视频| 亚洲精品视频免费在线观看| 国语自产精品视频在线看一大j8| 91sao在线观看国产| 久久的精品视频| 亚州精品天堂中文字幕| 欧美午夜精品在线| 成人有码视频在线播放| 亚洲精品98久久久久久中文字幕|