日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

javascript 模块模式

發(fā)布時(shí)間:2024/4/14 javascript 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 javascript 模块模式 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

模塊模式是JavaScript一種常用的編碼模式。這是一般的理解,但也有一些高級(jí)應(yīng)用沒有得到很多關(guān)注。在本文中,我將回顧基礎(chǔ)知識(shí),瀏覽一些不錯(cuò)的高級(jí)技巧,甚至我認(rèn)為是原生基礎(chǔ)的。

基礎(chǔ)知識(shí)

首先我們開始簡(jiǎn)單概述模型模式。如果你已經(jīng)很熟悉模型模式,可以直接閱讀“高級(jí)模式”。

匿名閉包

這是一切成為可能的基礎(chǔ),也是JavaScript最好的特性。我們將簡(jiǎn)單的創(chuàng)建匿名函數(shù),并立即執(zhí)行。所有函數(shù)內(nèi)部代碼都在閉包(closure)內(nèi)。它提供了整個(gè)應(yīng)用生命周期的私有和狀態(tài)。
?

  • (function () {
  • ? ? ? ? // ... all vars and functions are in this scope only
  • ? ? ? ? // still maintains access to all globals
  • }());
  • 注意匿名函數(shù)周圍的()。這是語言的要求。關(guān)鍵字function一般認(rèn)為是函數(shù)聲明,包括()就是函數(shù)表達(dá)式。

    引入全局

    JavaScript有個(gè)特性,稱為隱性全局。使用變量名稱時(shí),解釋器會(huì)從作用域向后尋找變量聲明。如果沒找到,變量會(huì)被假定入全局(以后可以全局調(diào)用)。如果會(huì)被分配使用,在還不存在時(shí)全局創(chuàng)建它。這意味著在匿名函數(shù)里使用全局變量很簡(jiǎn)單。不幸的是,這會(huì)導(dǎo)致代碼難以管理,文件中不容易區(qū)分(對(duì)人而言)哪個(gè)變量是全局的。

    幸好,匿名函數(shù)還有一個(gè)不錯(cuò)的選擇。全局變量作為參數(shù)傳遞給匿名函數(shù)。將它們引入我們的代碼中,既更清晰,又比使用隱性全局更快。下面是一個(gè)例子:
    ?

  • (function ($, YAHOO) {
  • ? ? ? ? // 當(dāng)前域有權(quán)限訪問全局jQuery($)和YAHOO
  • }(jQuery, YAHOO));
  • 模塊出口

    有時(shí)你不只想用全局變量,但你需要先聲明他們(模塊的全局調(diào)用)。我們用匿名函數(shù)的返回值,很容易輸出他們。這樣做就完成了基本的模塊模式。以下是一個(gè)完整例子:
    ?

  • var MODULE = (function () {
  • ? ? ? ? var my = {},
  • ? ? ? ? ? ? ? ? privateVariable = 1;
  • ? ? ? ??
  • ? ? ? ? function privateMethod() {
  • ? ? ? ? ? ? ? ? // ...
  • ? ? ? ? }
  • ? ? ? ??
  • ? ? ? ? my.moduleProperty = 1;
  • ? ? ? ? my.moduleMethod = function () {
  • ? ? ? ? ? ? ? ? // ...
  • ? ? ? ? };
  • ? ? ? ??
  • ? ? ? ? return my;
  • }());
  • 注意,我們聲明了一個(gè)全局模塊MODULE,有兩個(gè)公開屬性:方法MODULE.moduleMethod和屬性MODULE.moduleProperty。而且,匿名函數(shù)的閉包還維持了私有內(nèi)部狀態(tài)。同時(shí)學(xué)會(huì)之上的內(nèi)容,我們就很容易引入需要的全局變量,和輸出到全局變量。

    高級(jí)模式

    對(duì)許多用戶而言以上的還不足,我們可以采用以下的模式創(chuàng)造強(qiáng)大的,可擴(kuò)展的結(jié)構(gòu)。讓我們使用MODULE模塊,一個(gè)一個(gè)繼續(xù)。

    擴(kuò)充

    模塊模式的一個(gè)限制是整個(gè)模塊必須在一個(gè)文件里。任何人都了解長(zhǎng)代碼分割到不同文件的必要。還好,我們有很好的辦法擴(kuò)充模塊。(在擴(kuò)充文件)首先我們引入模塊(從全局),給他添加屬性,再輸出他。下面是一個(gè)例子擴(kuò)充模塊:
    ?

  • var MODULE = (function (my) {
  • ? ? ? ? my.anotherMethod = function () {
  • ? ? ? ? ? ? ? ? // 此前的MODULE返回my對(duì)象作為全局輸出,因此這個(gè)匿名函數(shù)的參數(shù)MODULE就 ? ? ? ? ?是上面MODULE匿名函數(shù)里的my
  • ? ? ? ? };
  • ?
  • ? ? ? ? return my;
  • }(MODULE));

  • 我們?cè)俅问褂胿ar關(guān)鍵字以保持一致性,雖然其實(shí)沒必要。代碼執(zhí)行后,模塊獲得一個(gè)新公開方法MODULE.anotherMethod。擴(kuò)充文件沒有影響模塊的私有內(nèi)部狀態(tài)。

    松耦合擴(kuò)充

    上面的例子需要我們首先創(chuàng)建模塊,然后擴(kuò)充它,這并不總是必要的。提升JavaScript應(yīng)用性能最好的操作就是異步加載腳本。因而我們可以創(chuàng)建靈活多部分的模塊,可以將他們無順序加載,以松耦合擴(kuò)充。每個(gè)文件應(yīng)有如下的結(jié)構(gòu):
    ?

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

  • 這個(gè)模式里,var語句是必須的,以標(biāo)記引入時(shí)不存在會(huì)創(chuàng)建。這意味著你可以像LABjs一樣同時(shí)加載所有模塊文件而不被阻塞。

    緊耦合擴(kuò)充

    雖然松耦合很不錯(cuò),但模塊上也有些限制。最重要的,你不能安全的覆寫模塊屬性(因?yàn)闆]有加載順序)。初始化時(shí)也無法使用其他文件定義的模塊屬性(但你可以在初始化后運(yùn)行)。緊耦合擴(kuò)充意味著一組加載順序,但是允許覆寫。下面是一個(gè)例子(擴(kuò)充最初定義的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,但依舊保持著私有內(nèi)部狀態(tài)。

    克隆和繼承
    ?

  • 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í)現(xiàn)巧妙的組合,但是犧牲了靈活性。正如我寫的,對(duì)象的屬性或方法不是拷貝,而是一個(gè)對(duì)象的兩個(gè)引用。修改一個(gè)會(huì)影響其他。這可能可以保持遞歸克隆對(duì)象的屬性固定,但無法固定方法,除了帶eval的方法。不過,我已經(jīng)完整的包含了模塊。(其實(shí)就是做了一次淺拷貝)。

    跨文件私有狀態(tài)

    一個(gè)模塊分割成幾個(gè)文件有一個(gè)嚴(yán)重缺陷。每個(gè)文件都有自身的私有狀態(tài),且無權(quán)訪問別的文件的私有狀態(tài)。這可以修復(fù)的。下面是一個(gè)松耦合擴(kuò)充的例子,不同擴(kuò)充文件之間保持了私有狀態(tài):
    ?

  • 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;
  • ? ? ? ? ? ? ? ? },//模塊加載后,調(diào)用以移除對(duì)_private的訪問權(quán)限
  • ? ? ? ? ? ? ? ? _unseal = my._unseal = my._unseal || function () {
  • ? ? ? ? ? ? ? ? ? ? ? ? my._private = _private;
  • ? ? ? ? ? ? ? ? ? ? ? ? my._seal = _seal;
  • ? ? ? ? ? ? ? ? ? ? ? ? my._unseal = _unseal;
  • ? ? ? ? ? ? ? ? };//模塊加載前,開啟對(duì)_private的訪問,以實(shí)現(xiàn)擴(kuò)充部分對(duì)私有內(nèi)容的操作
  • ? ? ? ??
  • ? ? ? ? // permanent access to _private, _seal, and _unseal
  • ? ? ? ??
  • ? ? ? ? return my;
  • }(MODULE || {}));
  • 何文件都可以在本地的變量_private中設(shè)置屬性,他會(huì)對(duì)別的擴(kuò)充立即生效(即初始化時(shí)所有擴(kuò)充的私有狀態(tài)都保存在_private變量,并被my._private輸出)。模塊完全加載了,應(yīng)用調(diào)用MODULE._seal()方法阻止對(duì)私有屬性的讀取(干掉my._private輸出)。如果此后模塊又需要擴(kuò)充,帶有一個(gè)私有方法。加載擴(kuò)充文件前調(diào)用MODULE._unseal()方法(恢復(fù)my._private,外部恢復(fù)操作權(quán)限)。加載后調(diào)用再seal()。

    這個(gè)模式一直隨我工作至今,我還沒看到別的地方這樣做的。我覺得這個(gè)模式很有用,值得寫上。

    子模塊

    最后的高級(jí)模式實(shí)際上最簡(jiǎn)單。有很多好方法創(chuàng)建子模塊。和創(chuàng)建父模塊是一樣的:
    ?

  • MODULE.sub = (function () {
  • ? ? ? ? var my = {};
  • ? ? ? ? // 就是多一級(jí)命名空間
  • ? ? ? ??
  • ? ? ? ? return my;
  • }());
  • 雖然很簡(jiǎn)單,但我還是提一下。子模塊有所有正常模塊的功能,包括擴(kuò)充和私有狀態(tài)。

    總結(jié)

    大多數(shù)高級(jí)模式可以互相組合成更多有用的模式。如果要我提出一個(gè)復(fù)雜應(yīng)用的設(shè)計(jì)模式,我會(huì)組合松耦合、私有狀態(tài)和子模塊。

    這里我還沒有涉及性能,不過我有個(gè)小建議:模塊模式是性能增益的。他簡(jiǎn)化了許多,加快代碼下載。松耦合可以無阻塞并行下載,等價(jià)于提高下載速度。可能初始化比別的方法慢一點(diǎn),但值得權(quán)衡。只要全局正確的引入,運(yùn)行性能不會(huì)有任何損失,可能還因?yàn)榫植孔兞亢透俚囊?#xff0c;加快子模塊的加載。

    最后,一個(gè)例子動(dòng)態(tài)加載子模塊到父模塊(動(dòng)態(tài)創(chuàng)建)中。這里就不用私有狀態(tài)了,其實(shí)加上也很簡(jiǎn)單。這段代碼允許整個(gè)復(fù)雜分成的代碼核心及其子模塊等平行加載完全。
    ?

  • 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));
  • 轉(zhuǎn)載于:https://my.oschina.net/niejianbo/blog/857600

    總結(jié)

    以上是生活随笔為你收集整理的javascript 模块模式的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。