国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

兼容多種模塊規(guī)范(AMD,CMD,Node)的代碼

Shonim / 1819人閱讀

摘要:主要區(qū)別是需要在聲明模塊時指定所有的依賴,通過形參傳遞依賴到模塊內(nèi)容中。

前言

昨天,公司同事問了我如下一個問題:

說他在看一個插件時,看到了源碼結(jié)構(gòu)如截圖所示,他知道(function(){})()是一種立即執(zhí)行函數(shù),但是在截圖中,最后的那個圓括號里又寫了一個函數(shù)function($,ChineseDistricts){...},這個函數(shù)暫且稱為“匿名函數(shù)1”,function (factory){...}暫且稱為“”匿名函數(shù)2”,意思是不是:把匿名函數(shù)1傳入到匿名函數(shù)2的參數(shù)factory中,然后檢測當前環(huán)境。如果檢測到了全局環(huán)境中存在exports對象,則證明是node環(huán)境,如果是node環(huán)境,則用factory(require("jquery"), require("ChineseDistricts"))這個方法來執(zhí)行匿名函數(shù)1,因為Node是基于模塊的,所以在Node中要使用這個插件的話,必須用require()方法把匿名函數(shù)2中需要的參數(shù)"$"和"ChineseDistricts"以模塊的方式給引用進來?

看到截圖的代碼和它的疑問,請接著往下看......

一、兼容多種模塊規(guī)范(AMD,CMD,Node)的代碼

在JavaScript模塊化開發(fā)中,為了讓同一個模塊可以運行在前后端,以及兼容多種模塊規(guī)范(AMD,CMD,Node),類庫開發(fā)者需要將類庫代碼包裝在一個閉包內(nèi)。

1.AMD規(guī)范

AMD,即“異步模塊定義”。主要實現(xiàn)比如: RequireJS。

其模塊引用方式如下:define(id?,dependencies?,factory);

其中,id及依賴是可選的。其與CommonJS方式相似的地方在于factory的內(nèi)容就是實際代碼的內(nèi)容,下面是一個簡單的例子:

define(function(){
  var exports = {};
  exports.say = function(){
    alert("hello");
  };
  return exports;
});

2.CMD規(guī)范

CMD規(guī)范,與AMD類似,區(qū)別主要在于定義模塊和依賴引入的地方。主要實現(xiàn)比如: SeaJS。

主要區(qū)別是:AMD需要在聲明模塊時指定所有的依賴,通過形參傳遞依賴到模塊內(nèi)容中。

define(["dep1","dep2"],function(dep1,dep2){
  return function(){};
});

與AMD相比,CMD更接近Node對CommonJS規(guī)范的定義:

define(factory);

在依賴部分,CMD支持動態(tài)引入,如下:

define(function(require,exports,module){
  // Todo
});

require、exports、module通過形參傳遞給模塊,在需要依賴模塊時,隨時調(diào)用require引入即可。

3.CommonJS的模塊實現(xiàn)

CommonJS的模塊引用使用require,如下:

var http = require("http");

4.Node的模塊實現(xiàn)

在Node中引入模塊,需要經(jīng)過下面3個步驟:路徑分析;文件定位;編譯執(zhí)行。主要用require()方法來查找模塊。

5.兼容多種模塊規(guī)范

為了讓同一個模塊可以運行在前后端,在開發(fā)過程中需要考慮兼容前后端問題,以下代碼演示如何將hello()方法定義到不同的運行環(huán)境中,它能夠兼容AMD、CMD、Node以及常見的瀏覽器環(huán)境中:

;(function (name, definition) {
  // 檢測上下文環(huán)境是否為AMD或CMD
  var hasDefine = typeof define === "function",
    // 檢查上下文環(huán)境是否為Node
    hasExports = typeof module !== "undefined" && module.exports;
 
  if (hasDefine) {
    // AMD環(huán)境或CMD環(huán)境
    define(definition);
  } else if (hasExports) {
    // 定義為普通Node模塊
    module.exports = definition();
  } else {
    // 將模塊的執(zhí)行結(jié)果掛在window變量中,在瀏覽器中this指向window對象
    this[name] = definition();
  }
})("hello", function () {
  var hello = function () {};
  return hello;
});
二、如何封裝Node.js和前端通用的模塊

在Node.js中對模塊載入和執(zhí)行進行了包裝,使得模塊文件中的變量在一個閉包中,不會污染全局變量,和他人沖突。

前端模塊通常是我們開發(fā)人員為了避免和他人沖突才把模塊代碼放置在一個閉包中。

如何封裝Node.js和前端通用的模塊,我們可以參考Underscore.js 實現(xiàn),他就是一個Node.js和前端通用的功能函數(shù)模塊,查看代碼:

// Create a safe reference to the Underscore object for use below.
  var _ = function(obj) {
    if (obj instanceof _) return obj;
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
  };
 
  // Export the Underscore object for **Node.js**, with
  // backwards-compatibility for the old `require()` API. If we"re in
  // the browser, add `_` as a global object via a string identifier,
  // for Closure Compiler "advanced" mode.
  if (typeof exports !== "undefined") {
    if (typeof module !== "undefined" && module.exports) {
      exports = module.exports = _;
    }
    exports._ = _;
  } else {
    root._ = _;
  }

通過判斷exports是否存在來決定將局部變量 _ 賦值給exports,向后兼容舊的require() API,如果在瀏覽器中,通過一個字符串標識符“_”作為一個全局對象;完整的閉包如下:

(function() {
 
  // Baseline setup
  // --------------
 
  // Establish the root object, `window` in the browser, or `exports` on the server.
  var root = this;
 
  // Create a safe reference to the Underscore object for use below.
  var _ = function(obj) {
    if (obj instanceof _) return obj;
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
  };
 
  // Export the Underscore object for **Node.js**, with
  // backwards-compatibility for the old `require()` API. If we"re in
  // the browser, add `_` as a global object via a string identifier,
  // for Closure Compiler "advanced" mode.
  if (typeof exports !== "undefined") {
    if (typeof module !== "undefined" && module.exports) {
      exports = module.exports = _;
    }
    exports._ = _;
  } else {
    root._ = _;
  }
}).call(this);

通過function定義構(gòu)建了一個閉包,call(this)是將function在this對象下調(diào)用,以避免內(nèi)部變量污染到全局作用域。瀏覽器中,this指向的是全局對象(window對象),將“_”變量賦在全局對象上“root._”,以供外部調(diào)用。

和Underscore.js 類似的Lo-Dash,也是使用了類似的方案,只是兼容了AMD模塊載入的兼容:

;(function() {
 
  /** Used as a safe reference for `undefined` in pre ES5 environments */
  var undefined;
    /** Used to determine if values are of the language type Object */
      var objectTypes = {
        "boolean": false,
        "function": true,
        "object": true,
        "number": false,
        "string": false,
        "undefined": false
      };
  /** Used as a reference to the global object */
  var root = (objectTypes[typeof window] && window) || this;
 
  /** Detect free variable `exports` */
  var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
 
  /** Detect free variable `module` */
  var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
 
  /** Detect the popular CommonJS extension `module.exports` */
  var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
 
/*--------------------------------------------------------------------------*/
 
  // expose Lo-Dash
  var _ = runInContext();
 
  // some AMD build optimizers, like r.js, check for condition patterns like the following:
  if (typeof define == "function" && typeof define.amd == "object" && define.amd) {
    // Expose Lo-Dash to the global object even when an AMD loader is present in
    // case Lo-Dash was injected by a third-party script and not intended to be
    // loaded as a module. The global assignment can be reverted in the Lo-Dash
    // module by its `noConflict()` method.
    root._ = _;
 
    // define as an anonymous module so, through path mapping, it can be
    // referenced as the "underscore" module
    define(function() {
      return _;
    });
  }
  // check for `exports` after `define` in case a build optimizer adds an `exports` object
  else if (freeExports && freeModule) {
    // in Node.js or RingoJS
    if (moduleExports) {
      (freeModule.exports = _)._ = _;
    }
    // in Narwhal or Rhino -require
    else {
      freeExports._ = _;
    }
  }
  else {
    // in a browser or Rhino
    root._ = _;
  }
}.call(this));

再來看看Moment.js的封裝閉包主要代碼:

(function (undefined) {
    var moment;
    // check for nodeJS
    var hasModule = (typeof module !== "undefined" && module.exports);
/************************************
        Exposing Moment
    ************************************/
 
    function makeGlobal(deprecate) {
        var warned = false, local_moment = moment;
        /*global ender:false */
        if (typeof ender !== "undefined") {
            return;
        }
        // here, `this` means `window` in the browser, or `global` on the server
        // add `moment` as a global object via a string identifier,
        // for Closure Compiler "advanced" mode
        if (deprecate) {
            this.moment = function () {
                if (!warned && console && console.warn) {
                    warned = true;
                    console.warn(
                            "Accessing Moment through the global scope is " +
                            "deprecated, and will be removed in an upcoming " +
                            "release.");
                }
                return local_moment.apply(null, arguments);
            };
        } else {
            this["moment"] = moment;
        }
    }
 
    // CommonJS module is defined
    if (hasModule) {
        module.exports = moment;
        makeGlobal(true);
    } else if (typeof define === "function" && define.amd) {
        define("moment", function (require, exports, module) {
            if (module.config().noGlobal !== true) {
                // If user provided noGlobal, he is aware of global
                makeGlobal(module.config().noGlobal === undefined);
            }
 
            return moment;
        });
    } else {
        makeGlobal();
    }
}).call(this);

從上面的幾個例子可以看出,在封裝Node.js和前端通用的模塊時,可以使用以下邏輯:

if (typeof exports !== "undefined") {
    exports.** = **;
} else {
    this.** = **;
}

即,如果exports對象存在,則將局部變量裝載在exports對象上,如果不存在,則裝載在全局對象上。如果加上ADM規(guī)范的兼容性,那么多加一句判斷:

if (typeof define === "function" && define.amd){}

參考鏈接:
1.http://www.css88.com/archives...
2.http://www.css88.com/archives...

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/89165.html

相關(guān)文章

  • 前端模塊化進程,commonJS,AMDCMD對比

    摘要:是另一種模塊化方案,它與很類似,不同點在于推崇依賴前置提前執(zhí)行,推崇依賴就近延遲執(zhí)行。 commonJS規(guī)范 隨著前端技術(shù)的不斷發(fā)展,項目越來越大,越來越不好管理,多人開發(fā)越來讓開發(fā)者頭疼,于是出現(xiàn)了命名空間,這沒有辦法的辦法,但是所有變量都是全局的話,管理非常混亂,而且在Node 出現(xiàn)前,javascript 在服務(wù)器端基本沒有市場,經(jīng)過javascript 不斷努力,社區(qū)為 jav...

    firim 評論0 收藏0
  • nodejs筆記-模塊機制

    摘要:模塊中定義的全局變量只作用于該文件內(nèi)部,不污染其他模塊。由純編寫的部分稱為內(nèi)建模塊,例等模塊部分使用編寫。兼容多種模塊規(guī)范檢測是否為或者檢測是否為或環(huán)境定義為普通模塊將模塊執(zhí)行結(jié)果掛載在對象下 1.為什么要CommonJS規(guī)范 javascript存在的缺點 沒有模塊系統(tǒng) 標準庫比較少 沒有標準接口 缺乏包管理系統(tǒng) CommonJS規(guī)范的提出,彌補了javascript沒有標準的缺...

    lscho 評論0 收藏0
  • OMD: javascript模塊化開發(fā)兼容CommonJS, AMD, CMD 以及 原生 JS

    摘要:它就是一套兼容方案,目前兼容的有以及原生支持。返回值問題在第一次使用時,。具體是什么意義呢的返回值,其實就是插件提供的對外接口,而實際上,就是一個對象。而在環(huán)境下,只需要將這個返回值賦予即可完成該模塊的接口。 有更新,請到github上看源碼 什么是OMD 在node.js流行起來之前,javascript的開發(fā)方式都是函數(shù)式的順序依賴關(guān)系,直到node火起來。CommonJS其實首先...

    lavor 評論0 收藏0
  • 關(guān)于JavaScript模塊規(guī)范之CommonJSAMDCMD

    摘要:所有依賴這個模塊的語句,都定義在一個回調(diào)函數(shù)中,等到加載完成之后,這個回調(diào)函數(shù)才會運行。也采用語句加載模塊,但是不同于,它要求兩個參數(shù)第一個參數(shù),是一個數(shù)組,里面的成員就是要加載的模塊第二個參數(shù),則是加載成功之后的回調(diào)函數(shù)。 本篇文章來自對文章《js模塊化編程之徹底弄懂CommonJS和AMD/CMD!》的總結(jié),大部分摘自文章原話,本人只是為了學(xué)習(xí)方便做的筆記,之后有新的體會會及時補充...

    binaryTree 評論0 收藏0
  • 前端工程師必備:前端模塊

    摘要:規(guī)范則是非同步加載模塊,允許指定回調(diào)函數(shù),可以實現(xiàn)異步加載依賴模塊,并且會提前加載由于主要用于服務(wù)器編程,模塊文件一般都已經(jīng)存在于本地硬盤,所以加載起來比較快,不用考慮非同步加載的方式,所以規(guī)范比較適用。 JS模塊化 模塊化的理解 什么是模塊? 將一個復(fù)雜的程序依據(jù)一定的規(guī)則(規(guī)范)封裝成幾個塊(文件), 并進行組合在一起; 塊的內(nèi)部數(shù)據(jù)/實現(xiàn)是私有的, 只是向外部暴露一些接口(...

    Render 評論0 收藏0

發(fā)表評論

0條評論

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