隨著RequireJS成為最流行的實(shí)現(xiàn)方式,異步模塊規(guī)范(AMD)在前端界已經(jīng)被廣泛認(rèn)同。
下面是只依賴(lài)jquery的模塊foo的代碼:
// 文件名: foo.js
define(['jquery'], function ($) {
// 方法
function myFunc(){};
// 暴露公共方法
return myFunc;
});
還有稍微復(fù)雜點(diǎn)的例子,下面的代碼依賴(lài)了多個(gè)組件并且暴露多個(gè)方法:
// 文件名: foo.js
define(['jquery', 'underscore'], function ($, _) {
// 方法
function a(){}; // 私有方法,因?yàn)闆](méi)有被返回(見(jiàn)下面)
function b(){}; // 公共方法,因?yàn)楸环祷亓?function c(){}; // 公共方法,因?yàn)楸环祷亓?
// 暴露公共方法
return {
b: b,
c: c
}
});
定義的第一個(gè)部分是一個(gè)依賴(lài)數(shù)組,第二個(gè)部分是回調(diào)函數(shù),只有當(dāng)依賴(lài)的組件可用時(shí)(像RequireJS這樣的腳本加載器會(huì)負(fù)責(zé)這一部分,包括找到文件路徑)回調(diào)函數(shù)才被執(zhí)行。
注意,依賴(lài)組件和變量的順序是一一對(duì)應(yīng)的(例如,jquery->$, underscore->)。
同時(shí)注意,我們可以用任意的變量名來(lái)表示依賴(lài)組件。假如我們把$改成$$,在函數(shù)體里面的所有對(duì)jQuery的引用都由$變成了$$。
還要注意,最重要的是你不能在回調(diào)函數(shù)外面引用變量$和,因?yàn)樗鄬?duì)其它代碼是獨(dú)立的。這正是模塊化的目的所在!
CommonJS
如果你用Node寫(xiě)過(guò)東西的話,你可能會(huì)熟悉CommonJS的風(fēng)格(node使用的格式與之相差無(wú)幾)。因?yàn)橛蠦rowserify,它也一直被前端界廣泛認(rèn)同。
就像前面的格式一樣,下面是用CommonJS規(guī)范實(shí)現(xiàn)的foo模塊的寫(xiě)法:
// 文件名: foo.js
// 依賴(lài)
var $ = require('jquery');
// 方法
function myFunc(){};
// 暴露公共方法(一個(gè))
module.exports = myFunc;
還有更復(fù)雜的例子,下面的代碼依賴(lài)了多個(gè)組件并且暴露多個(gè)方法:
// 文件名: foo.js
var $ = require('jquery');
var _ = require('underscore');
// methods
function a(){}; // 私有方法,因?yàn)樗鼪](méi)在module.exports中 (見(jiàn)下面)
function b(){}; // 公共方法,因?yàn)樗趍odule.exports中定義了
function c(){}; // 公共方法,因?yàn)樗趍odule.exports中定義了
// 暴露公共方法
module.exports = {
b: b,
c: c
};
UMD: 通用模塊規(guī)范
既然CommonJs和AMD風(fēng)格一樣流行,似乎缺少一個(gè)統(tǒng)一的規(guī)范。所以人們產(chǎn)生了這樣的需求,希望有支持兩種風(fēng)格的“通用”模式,于是通用模塊規(guī)范(UMD)誕生了。
不得不承認(rèn),這個(gè)模式略難看,但是它兼容了AMD和CommonJS,同時(shí)還支持老式的“全局”變量規(guī)范:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node, CommonJS之類(lèi)的
module.exports = factory(require('jquery'));
} else {
// 瀏覽器全局變量(root 即 window)
root.returnExports = factory(root.jQuery);
}
}(this, function ($) {
// 方法
function myFunc(){};
// 暴露公共方法
return myFunc;
}));
保持跟上面例子一樣的模式,下面是更復(fù)雜的例子,它依賴(lài)了多個(gè)組件并且暴露多個(gè)方法:
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD
define(['jquery', 'underscore'], factory);
} else if (typeof exports === 'object') {
// Node, CommonJS之類(lèi)的
module.exports = factory(require('jquery'), require('underscore'));
} else {
// 瀏覽器全局變量(root 即 window)
root.returnExports = factory(root.jQuery, root._);
}
}(this, function ($, _) {
// 方法
function a(){}; // 私有方法,因?yàn)樗鼪](méi)被返回 (見(jiàn)下面)
function b(){}; // 公共方法,因?yàn)楸环祷亓? function c(){}; // 公共方法,因?yàn)楸环祷亓?
// 暴露公共方法
return {
b: b,
c: c
}
}));