鏈接:http://www.zhihu.com/question/20351507/answer/14859415
AMD 規范在這里:
https://github.com/amdjs/amdjs-api/wiki/AMD
CMD 規范在這里: https://github.com/seajs/seajs/issues/242
AMD 是 RequireJS 在推廣過程中對模塊定義的規范化產出。
CMD 是 SeaJS 在推廣過程中對模塊定義的規范化產出。
類似的還有 CommonJS Modules/2.0 規范,是 BravoJS 在推廣過程中對模塊定義的規范化產出。
還有不少⋯⋯
這些規范的目的都是為了 JavaScript 的模塊化開發,特別是在瀏覽器端的。
目前這些規范的實現都能達成 瀏覽器端模塊化開發的目的。
區別:
1. 對於依賴的模塊,AMD 是 提前執行,CMD 是 延遲執行。不過 RequireJS 從 2.0 開始,也改成可以延遲執行(根據寫法不同,處理方式不同)。CMD 推崇 as lazy as possible.
2. CMD 推崇 依賴就近,AMD 推崇 依賴前置。看代碼:
// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此處略去 100 行
var b = require('./b') // 依賴可以就近書寫
b.doSomething()
// ...
})
// AMD 默認推薦的是
define(['./a', './b'], function(a, b) { // 依賴必須一開始就寫好
a.doSomething()
// 此處略去 100 行
b.doSomething()
...
})
雖然 AMD 也支持 CMD 的寫法,同時還支持將 require 作為依賴項傳遞,但 RequireJS 的作者默認是最喜歡上面的寫法,也是官方文檔里默認的模塊定義寫法。
3. AMD 的 API 默認是 一個當多個用,CMD 的 API 嚴格區分,推崇 職責單一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,沒有全局 require,而是根據模塊系統的完備性,提供 seajs.use 來實現模塊系統的加載啟動。CMD 里,每個 API 都 簡單純粹。
4. 還有一些細節差異,具體看這個規范的定義就好,就不多說了。
另外,SeaJS 和 RequireJS 的差異,可以參考
CMD 規范在這里: https://github.com/seajs/seajs/issues/242
AMD 是 RequireJS 在推廣過程中對模塊定義的規范化產出。
CMD 是 SeaJS 在推廣過程中對模塊定義的規范化產出。
類似的還有 CommonJS Modules/2.0 規范,是 BravoJS 在推廣過程中對模塊定義的規范化產出。
還有不少⋯⋯
這些規范的目的都是為了 JavaScript 的模塊化開發,特別是在瀏覽器端的。
目前這些規范的實現都能達成 瀏覽器端模塊化開發的目的。
區別:
1. 對於依賴的模塊,AMD 是 提前執行,CMD 是 延遲執行。不過 RequireJS 從 2.0 開始,也改成可以延遲執行(根據寫法不同,處理方式不同)。CMD 推崇 as lazy as possible.
2. CMD 推崇 依賴就近,AMD 推崇 依賴前置。看代碼:
// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此處略去 100 行
var b = require('./b') // 依賴可以就近書寫
b.doSomething()
// ...
})
// AMD 默認推薦的是
define(['./a', './b'], function(a, b) { // 依賴必須一開始就寫好
a.doSomething()
// 此處略去 100 行
b.doSomething()
...
})
雖然 AMD 也支持 CMD 的寫法,同時還支持將 require 作為依賴項傳遞,但 RequireJS 的作者默認是最喜歡上面的寫法,也是官方文檔里默認的模塊定義寫法。
3. AMD 的 API 默認是 一個當多個用,CMD 的 API 嚴格區分,推崇 職責單一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,沒有全局 require,而是根據模塊系統的完備性,提供 seajs.use 來實現模塊系統的加載啟動。CMD 里,每個 API 都 簡單純粹。
4. 還有一些細節差異,具體看這個規范的定義就好,就不多說了。
另外,SeaJS 和 RequireJS 的差異,可以參考
執行模塊的機制大不一樣
-----------------------------------
由於 RequireJS 是執行的 AMD 規范, 因此所有的依賴模塊都是先執行.
使用 RequireJS 默認定義模塊的方式, 在理解上會更清楚一些, 但個人還是偏愛 require('./mod1') 這樣的方式
define(['dep1', 'dep2'], function (dep1, dep2) {
//Define the module value by returning a value.
return function () {};
});
希望文章沒有誤人子弟, 謝謝 @Jaward華仔 的意見, 請大家多看評論, 評論更有料...
---------------------------------------------------------------------------
SeaJS對模塊的態度是懶執行, 而RequireJS對模塊的態度是預執行
不明白? 讓我們來舉個例子
如下模塊通過SeaJS/RequireJS來加載, 執行結果會是怎樣?
define(function(require, exports, module) {
console.log('require module: main');
var mod1 = require('./mod1');
mod1.hello();
var mod2 = require('./mod2');
mod2.hello();
return {
hello: function() {
console.log('hello main');
}
};
});
猜猜看?
先試試SeaJS的執行結果
require module: main
require module: mod1
hello mod1
require module: mod2
hello mod2
hello main
再來是RequireJS的執行結果
require module: mod1
require module: mod2
require module: main
hello mod1
hello mod2
hello main
RequireJS你坑的我一滾啊, 這也就是為什么我不喜歡RequireJS的原因, 坑隱藏得太深了.
終於明白 玉伯說的那句: " RequireJS 是沒有明顯的 bug,SeaJS 是明顯沒有 bug"是什么意思了
因此我們得出結論(分別使用SeaJS 2.0.0和RequireJS 2.1.6進行測試)
-------------------------
SeaJS只會在真正需要使用(依賴)模塊時才執行該模塊
SeaJS是異步加載模塊的沒錯, 但執行模塊的順序也是嚴格按照模塊在代碼中出現(require)的順序, 這樣才更符合邏輯吧! 你說呢, RequireJS?
而RequireJS會先盡早地執行(依賴)模塊, 相當於所有的require都被提前了, 而且模塊執行的順序也不一定100%就是先mod1再mod2
因此你看到執行順序和你預想的完全不一樣! 顫抖吧~ RequireJS!
詳細的代碼請參考
-------------------------
SeaJS測試加載/執行模塊
RequireJS測試加載/執行模塊
后記
-------
注意我這里說的是執行(真正運行define中的代碼)模塊, 而非加載(load文件)模塊.
模塊的加載都是並行的, 沒有區別, 區別在於執行模塊的時機, 或者說是解析.
為了說明阻塞的問題, 翠花上圖
注意圖中巨大的pinyin-dict.js模塊, 取自 pinyin.js, 復制了N次后以增加它的"重量", 增強演示效果, 大家有興趣的話可以親手試試.
可以很明顯的看出RequireJS的做法是並行加載所有依賴的模塊, 並完成解析后, 再開始執行其他代碼, 因此執行結果只會"停頓"1次, 完成整個過程是會比SeaJS要快.
而SeaJS一樣是並行加載所有依賴的模塊, 但不會立即執行模塊, 等到真正需要(require)的時候才開始解析, 這里耗費了時間, 因為這個特例中的模塊巨大, 因此造成"停頓"2次的現象, 這就是我所說的SeaJS中的"懶執行".
最后感謝大家的各種意見建議, 我這里並沒有說SeaJS與RequireJS哪個更好一些, 僅僅是為了說明下他們的區別, 各種取舍請大家根據實際情況來定, 希望能幫到大家.
-----------------------------------
由於 RequireJS 是執行的 AMD 規范, 因此所有的依賴模塊都是先執行.
使用 RequireJS 默認定義模塊的方式, 在理解上會更清楚一些, 但個人還是偏愛 require('./mod1') 這樣的方式
define(['dep1', 'dep2'], function (dep1, dep2) {
//Define the module value by returning a value.
return function () {};
});
希望文章沒有誤人子弟, 謝謝 @Jaward華仔 的意見, 請大家多看評論, 評論更有料...
---------------------------------------------------------------------------
SeaJS對模塊的態度是懶執行, 而RequireJS對模塊的態度是預執行
不明白? 讓我們來舉個例子
![]() |
如下模塊通過SeaJS/RequireJS來加載, 執行結果會是怎樣?
define(function(require, exports, module) {
console.log('require module: main');
var mod1 = require('./mod1');
mod1.hello();
var mod2 = require('./mod2');
mod2.hello();
return {
hello: function() {
console.log('hello main');
}
};
});
猜猜看?
![]() |
先試試SeaJS的執行結果
require module: main
require module: mod1
hello mod1
require module: mod2
hello mod2
hello main
![]() |
很正常嘛, 我也是這么想的...
|
再來是RequireJS的執行結果
require module: mod1
require module: mod2
require module: main
hello mod1
hello mod2
hello main
![]() |
神馬情況? 你他么是在逗我嗎?
|
RequireJS你坑的我一滾啊, 這也就是為什么我不喜歡RequireJS的原因, 坑隱藏得太深了.
終於明白 玉伯說的那句: " RequireJS 是沒有明顯的 bug,SeaJS 是明顯沒有 bug"是什么意思了
因此我們得出結論(分別使用SeaJS 2.0.0和RequireJS 2.1.6進行測試)
-------------------------
SeaJS只會在真正需要使用(依賴)模塊時才執行該模塊
SeaJS是異步加載模塊的沒錯, 但執行模塊的順序也是嚴格按照模塊在代碼中出現(require)的順序, 這樣才更符合邏輯吧! 你說呢, RequireJS?
而RequireJS會先盡早地執行(依賴)模塊, 相當於所有的require都被提前了, 而且模塊執行的順序也不一定100%就是先mod1再mod2
因此你看到執行順序和你預想的完全不一樣! 顫抖吧~ RequireJS!
詳細的代碼請參考
-------------------------
SeaJS測試加載/執行模塊
RequireJS測試加載/執行模塊
后記
-------
注意我這里說的是執行(真正運行define中的代碼)模塊, 而非加載(load文件)模塊.
模塊的加載都是並行的, 沒有區別, 區別在於執行模塊的時機, 或者說是解析.
為了說明阻塞的問題, 翠花上圖
![]() |
SeaJS的懶執行
|
![]() |
RequireJS的預執行
|
注意圖中巨大的pinyin-dict.js模塊, 取自 pinyin.js, 復制了N次后以增加它的"重量", 增強演示效果, 大家有興趣的話可以親手試試.
可以很明顯的看出RequireJS的做法是並行加載所有依賴的模塊, 並完成解析后, 再開始執行其他代碼, 因此執行結果只會"停頓"1次, 完成整個過程是會比SeaJS要快.
而SeaJS一樣是並行加載所有依賴的模塊, 但不會立即執行模塊, 等到真正需要(require)的時候才開始解析, 這里耗費了時間, 因為這個特例中的模塊巨大, 因此造成"停頓"2次的現象, 這就是我所說的SeaJS中的"懶執行".
最后感謝大家的各種意見建議, 我這里並沒有說SeaJS與RequireJS哪個更好一些, 僅僅是為了說明下他們的區別, 各種取舍請大家根據實際情況來定, 希望能幫到大家.