Simplified CommonJS wrapper 與 AMD 標準定義模塊差別

標準的 AMD 模塊定義

一個標準的 AMD 模塊看起來是這樣子:git

define(['foo', 'foo/bar'], function (foo, bar) {
    return {
        doSomething: function () {
            console.log(foo + bar);
        }
    };
});

模塊 foofoo/bar 在工廠函數被調用以前完成加載,並做爲參數傳遞給工廠函數。github

工做原理:數組

  1. RequireJS 讀取依賴模塊數組。
  2. 繼而檢查當前上下文是否已註冊這些依賴模塊:
    1. 若是模塊已註冊,則直接使用;
    2. 不然:
      1. 經過檢查 paths.config 和當前模塊路徑,將模塊 ID 解析爲 URI。
      2. 加載 URI 指向的源文件。
      3. 若是依賴模塊是 AMD 模塊,則重複以上過程直至全部依賴模塊被加載完畢。
  3. 當全部依賴模塊準備穩當,將依賴模塊做爲參數去調用工廠函數,工廠函數的返回值做爲新模塊被註冊到當前上下文。

Simplified CommonJS wrapper

若是你想讓別人像 CommonJS 模塊那樣使用你的模塊,尤爲是你的模塊擁有大量依賴模塊,你可使用 Simplified CommonJS wrapper。app

define (function (require, exports, module) {
    var foo = require('foo'),
          bar = require('foo/bar');

    exports.doSomething = function () {
        console.log(foo + bar);
    };
});

一個模塊被當作 CommonJS 模塊,它必須不能包含依賴模塊數組,而且工廠函數包含至少一個參數。函數

工做原理:requirejs

  1. RequireJS 檢查 define 函數調用是否沒有使用依賴模塊數組。
  2. 而後經過讀取 Function.prototype.length 來檢查工廠是否接受參數。
    1. 若是接受參數,則將該模塊視爲 CommonJS 模塊:
      1. 調用 Function.prototype.toString(),並找到全部工廠函數中全部同步的 require() 調用來肯定依賴模塊。
      2. 加載全部依賴模塊。
      3. 完成依賴模塊加載後,將特殊模塊 require, exportsmodule 做爲參數傳遞給工廠函數,而後將函數返回值或 module.exportsexports 註冊爲新模塊。
    2. 若是不接受參數,則將該模塊視爲標準 AMD 模塊(沒有依賴包),執行工廠函數並註冊函數返回值爲新模塊。

同步 require()

對於一個標準的 AMD 模塊,只要模塊在當前上下文註冊,你能夠同步調用 require() 函數。ui

define (['require', 'lorem/ipsum'], function (require) {
    // 由於模塊 lorem/ipsum 在依賴數組中。
    // 它會在工廠函數被調用前完成註冊,所以本段代碼是可行的。
    console.log(require('lorem/ipsum'));
});

但如下代碼會由於 dolor/amet 未註冊而失敗:prototype

define(['require'], function (require) {
    console.log(require('dolor/amet'));
});

由於咱們在 define 函數中使用了依賴數組,所以新模塊將被視爲標準 AMD 模塊,所以它不會掃描工廠函數代碼以獲取依賴數組。你將看到如下異常提示:code

Uncaught Error: Module name 'dolor/amet' has not been loaded yet for context: _接口

若是使用 Simplified CommonJS Wrapper,那麼 RequireJS 會在工廠函數調用前加載依賴包:

define (function (require) {
    console.log(require('dolor/amet'));
});

特殊模塊

標準 AMD 模塊中一樣可使用特殊模塊 require, exportsmodule

exports

define (['exports'], function (exports) {
    exports.foo = 'bar';
    exports.lorem = function (){
        console.log('ipsum');
    };
});

添加到 exports 上的屬性會自動成爲模塊的公開接口,工廠函數無需返回值。

module

如下模塊記錄了模塊 ID 和當前模塊的路徑。

define (['module'], function (module){
    console.log(module.id);
    console.log(module.uri);
});

require

require 模塊除了能夠加載依賴模塊,還能夠指出模塊源文件路徑。

  • require.toUrl(moduleName): 返回模塊源文件路徑。

PS:本文譯自 Differences between the Simplified CommonJS wrapper and standard AMD define

相關文章
相關標籤/搜索