CMD 模塊定義規範

CMD 模塊定義規範

在 Sea.js 中,全部 JavaScript 模塊都遵循 CMD(Common Module Definition) 模塊定義規範。該規範明確了模塊的基本書寫格式和基本交互規則。jquery

在 CMD 規範中,一個模塊就是一個文件。代碼的書寫格式以下:git

define(factory);

define Function

define 是一個全局函數,用來定義模塊。github

define define(factory)

define 接受 factory 參數,factory 能夠是一個函數,也能夠是一個對象或字符串。數組

factory 爲對象、字符串時,表示模塊的接口就是該對象、字符串。好比能夠以下定義一個 JSON 數據模塊:異步

define({ "foo": "bar" });

也能夠經過字符串定義模板模塊:async

define('I am a template. My name is {{name}}.');

factory 爲函數時,表示是模塊的構造方法。執行該構造方法,能夠獲得模塊向外提供的接口。factory 方法在執行時,默認會傳入三個參數:requireexports 和 module函數

define(function(require, exports, module) {

  // 模塊代碼

});

define define(id?, deps?, factory)

define 也能夠接受兩個以上參數。字符串 id 表示模塊標識,數組 deps 是模塊依賴。好比:工具

define('hello', ['jquery'], function(require, exports, module) {

  // 模塊代碼

});

id 和 deps 參數能夠省略。省略時,能夠經過構建工具自動生成。ui

注意:帶 id 和 deps 參數的 define 用法不屬於 CMD 規範,而屬於 Modules/Transport 規範。this

define.cmd Object

一個空對象,可用來斷定當前頁面是否有 CMD 模塊加載器:

if (typeof define === "function" && define.cmd) {
  // 有 Sea.js 等 CMD 模塊加載器存在
}

require Function

require 是 factory 函數的第一個參數。

require require(id)

require 是一個方法,接受 模塊標識 做爲惟一參數,用來獲取其餘模塊提供的接口。

define(function(require, exports) {

  // 獲取模塊 a 的接口
  var a = require('./a');

  // 調用模塊 a 的方法
  a.doSomething();

});

注意:在開發時,require 的書寫須要遵循一些 簡單約定

require.async require.async(id, callback?)

require.async 方法用來在模塊內部異步加載模塊,並在加載完成後執行指定回調。callback 參數可選。

define(function(require, exports, module) {

  // 異步加載一個模塊,在加載完成時,執行回調
  require.async('./b', function(b) {
    b.doSomething();
  });

  // 異步加載多個模塊,在加載完成時,執行回調
  require.async(['./c', './d'], function(c, d) {
    c.doSomething();
    d.doSomething();
  });

});

注意require 是同步往下執行,require.async 則是異步回調執行。require.async 通常用來加載可延遲異步加載的模塊。

require.resolve require.resolve(id)

使用模塊系統內部的路徑解析機制來解析並返回模塊路徑。該函數不會加載模塊,只返回解析後的絕對路徑。

define(function(require, exports) {

  console.log(require.resolve('./b'));
  // ==> http://example.com/path/to/b.js

});

這能夠用來獲取模塊路徑,通常用在插件環境或需動態拼接模塊路徑的場景下。

exports Object

exports 是一個對象,用來向外提供模塊接口。

define(function(require, exports) {

  // 對外提供 foo 屬性
  exports.foo = 'bar';

  // 對外提供 doSomething 方法
  exports.doSomething = function() {};

});

除了給 exports 對象增長成員,還能夠使用 return 直接向外提供接口。

define(function(require) {

  // 經過 return 直接提供接口
  return {
    foo: 'bar',
    doSomething: function() {};
  };

});

若是 return 語句是模塊中的惟一代碼,還可簡化爲:

define({
  foo: 'bar',
  doSomething: function() {};
});

上面這種格式特別適合定義 JSONP 模塊。

特別注意:下面這種寫法是錯誤的!

define(function(require, exports) {

  // 錯誤用法!!!
  exports = {
    foo: 'bar',
    doSomething: function() {};
  };

});

正確的寫法是用 return 或者給 module.exports 賦值:

define(function(require, exports, module) {

  // 正確寫法
  module.exports = {
    foo: 'bar',
    doSomething: function() {};
  };

});

提示exports 僅僅是 module.exports 的一個引用。在 factory 內部給 exports 從新賦值時,並不會改變module.exports 的值。所以給 exports 賦值是無效的,不能用來更改模塊接口。

module Object

module 是一個對象,上面存儲了與當前模塊相關聯的一些屬性和方法。

module.id String

模塊的惟一標識。

define('id', [], function(require, exports, module) {

  // 模塊代碼

});

上面代碼中,define 的第一個參數就是模塊標識。

module.uri String

根據模塊系統的路徑解析規則獲得的模塊絕對路徑。

define(function(require, exports, module) {

  console.log(module.uri); 
  // ==> http://example.com/path/to/this/file.js

});

通常狀況下(沒有在 define 中手寫 id 參數時),module.id 的值就是 module.uri,二者徹底相同。

module.dependencies Array

dependencies 是一個數組,表示當前模塊的依賴。

module.exports Object

當前模塊對外提供的接口。

傳給 factory 構造方法的 exports 參數是 module.exports 對象的一個引用。只經過 exports 參數來提供接口,有時沒法知足開發者的全部需求。 好比當模塊的接口是某個類的實例時,須要經過 module.exports 來實現:

define(function(require, exports, module) {

  // exports 是 module.exports 的一個引用
  console.log(module.exports === exports); // true

  // 從新給 module.exports 賦值
  module.exports = new SomeClass();

  // exports 再也不等於 module.exports
  console.log(module.exports === exports); // false

});

注意:對 module.exports 的賦值須要同步執行,不能放在回調函數裏。下面這樣是不行的:

// x.js
define(function(require, exports, module) {

  // 錯誤用法
  setTimeout(function() {
    module.exports = { a: "hello" };
  }, 0);

});

在 y.js 裏有調用到上面的 x.js:

// y.js
define(function(require, exports, module) {

  var x = require('./x');

  // 沒法馬上獲得模塊 x 的屬性 a
  console.log(x.a); // undefined

});

小結

這就是 CMD 模塊定義規範的全部內容。常常使用的 API 只有 definerequirerequire.asyncexports,module.exports 這五個。其餘 API 有個印象就好,在須要時再來查文檔,不用刻意去記。

與 RequireJS 的 AMD 規範相比,CMD 規範儘可能保持簡單,並與 CommonJS 和 Node.js 的 Modules 規範保持了很大的兼容性。經過 CMD 規範書寫的模塊,能夠很容易在 Node.js 中運行

相關文章
相關標籤/搜索