AMD規範與CMD規範的區別是什麼?html
在比較以前,咱們得先來了解下什麼是AMD規範?什麼是CMD規範?固然先申明一下,我我的也是總結下而已,也是網上看到的資料,本身總結下或者能夠說整理下而已,供你們更深刻的瞭解!由於咱們都知道 AMD規範:是 RequireJS 在推廣過程當中對模塊定義的規範化產出的,而CMD規範:是SeaJS 在推廣過程當中對模塊定義的規範化產出的。前端
什麼是CMD規範?jquery
在CMD中 一個模塊就是一個文件,以下代碼所示:json
//基本格式如:define(id, deps, factory)
// 好比以下代碼
define('hello',['jQuery'],function(require, exports, module) {
// 模塊代碼
});
define是一個全局函數,主要是用來定於模塊的。其中如上'hello'就是模塊名稱,['jquery']是依賴項,也能夠依賴於多項能夠以下寫法['jquery','',''],分別用逗號隔開,其中上面的id(模塊名稱)和deps(被依賴項) 是能夠省略的。省略時,那麼模塊名稱就是文件名稱。好比我有個文件叫a.js,那麼我定義模塊時候以下代碼所示:
define(function(require, exports, module) {
// 模塊代碼
});
那麼若是我想在b.js代碼裏面要依賴於a.js的話,那麼我能夠直接這樣寫:
define(function(require,exports,module){ var a = require('a')});
可是注意:帶有id 和 deps 是不屬於CMD規範的。因此在seaJS裏面 通常的寫法是不帶模塊名稱和依賴項的。就是如上的代碼格式。
下面看看 factory 在seajs裏面 factory既能夠是函數,對象或者字符串。factory爲對象 字符串時候,表示該模塊的接口就是該對象或者字符串,以下能夠定義一個json對象。
define({"aa":'bb'});和jsonp格式相似,不過這樣的數據對象是高度可用的,並且由於是靜態對象,他也是CDN友好的,能夠提升性能,好比說咱們 有個省市區這麼一個jSON格式要返回咱們前端,若是以傳統JSONP的形式提供給客戶端,它必須提供一個callback函數名,根據這個函數名動態生成返回數據,這使得標準JSONP數據必定不是CDN友好的。那麼咱們能夠利用這種格式
define({ provinces: [ { name: '上海', areas: ['浦東新區', '徐彙區']}, { name: '江蘇', cities: ['南京', '南通']} //..... ] });
假設這個文件名爲china.js,那麼若是某個模塊須要這個數據,只須要:
define(function(require,exports,module){
var china = require('./china'); //在這裏使用中國省市數據 });
當factory爲函數時,表示該模塊的構造方法,執行該構造方法,能夠獲得模塊向外提供的接口。默認會傳入三個參數require,exports,module.那麼咱們先來看看require參數吧!
require:
require是一個方法,他能夠解決依賴,用於獲取其餘模塊提供的接口,好比下面的a.js代碼以下
define(function(require, exports) {
exports.a = function(){
// 不少代碼
};
});api
那麼如今我想在b.js裏面調用a.js裏面的a方法。咱們能夠以下作:dom
define(function(require,exports){異步
var fun = require('./a');async
console.log(fun.a()); // 就能夠調用到及執行a函數了。函數
})性能
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.resolve(id)
使用模塊系統內部的路徑解析機制來解析並返回模塊路徑。該函數不會加載模塊,只返回解析後的絕對路徑。
define(function(require, exports) {
console.log(require.resolve('./b'));
// ==> http://example.com/path/to/b.js
});
exports
exports:是一個對象,用來向外提供模塊接口。
好比仍是上面的代碼:以下a.js裏面
define(function(require, exports) {
exports.a = function(){
// 不少代碼
};
});
或者以下書寫:
define(function(require, exports) {
return {
i: 'a',
a: function(){
// 執行相應的代碼
}
}
});
那麼若是我在b.js裏面想要調用a.js裏面的a方法,因爲a.js使用exports對外提供了接口a方法,那麼在b.js裏面 咱們只須要先這樣 var fun = require('./a');而後執行fun.a();就能夠執行a方法了。
module
module 是一個對象,上面存儲了與當前模塊相關聯的一些屬性和方法。其中exports是module.exports的一個引用。
module.exports的一個引用。
moudle.id
moudle.id
模塊的惟一標識。以下代碼:
define('id', [], function(require, exports, module) { // 模塊代碼 });
module.uri
根據模塊系統的路徑解析規則獲得的模塊絕對路徑。
define(function(require, exports, module) { console.log(module.uri); // ==> http://example.com/path/to/this/file.js });
等等屬性 具體能夠看seajs官網。原理是同樣的 由於seajs也採用的是CMD規範。
什麼是AMD規範?
以下官網代碼:
define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
exports.verb = function() {
return beta.verb();
//或者:
return require("beta").verb();
}
});
這裏的require函數讓你可以隨時去依賴一個模塊,即取得模塊的引用,從而即便模塊沒有做爲參數定義,也可以被使用;exports是定義的 alpha 模塊的實體,在其上定義的任何屬性和方法也就是alpha模塊的屬性和方法。經過exports.verb = ...就是爲alpha模塊定義了一個verb方法。例子中是簡單調用了模塊beta的verb方法。
其中上面的模塊名稱和依賴項 也能夠省略,那麼若是省略的話,那麼咱們能夠稱他們爲匿名函數,那麼一樣 模塊名稱就是文件名稱 和上面的CMD規範相似。上面的['',''] 參數表明了一組對所定義的模塊來講必須的依賴項。第三個參數('definition function')是一個用來爲你的模塊執行初始化的函數。一個最簡單的模塊能夠以以下方式定義:
// 模塊定義函數
// 依賴項(foo 和 bar)被映射爲函數的參數
define('myMoudle',['foo','bar'],function(foo,bar){
// 返回一個定義了模塊導出接口的值
// (也就是咱們想要導出後進行調用的功能)
// 在這裏建立模塊
var myModule = {
doStuff:function(){
console.log('Yay! Stuff');
}
}
return myModule;
});
還能夠這樣書寫:
// 另外一個例子能夠是...
define('myModule',['math', 'graph'], function ( math, graph ) {
// 請注意這是一個和 AMD 有些許不一樣的模式,但用幾種不一樣的方式
// 來定義模塊也是能夠的,由於語法在某些方面仍是比較靈活的
return {
plot: function(x, y){
return graph.drawPie(math.randomGrid(x,y));
}
}
};
});
另外一方面,require 則主要用來在頂層 JavaScript 文件中或需要動態讀取依賴時加載代碼。用法的一個實例以下:
// 假設 'foo' 和 'bar' 是兩個外部模塊
// 在本例中,這兩個模塊被加載後的 'exports' 被當作兩個參數傳遞到了回調函數中
// 因此能夠像這樣來訪問他們
require(['foo', 'bar'], function ( foo, bar ) {
// 這裏寫其他的代碼
foo.doSomething();
});
define(function ( require ) {
var isReady = false,
foobar;
// 請注意在模塊定義內部內聯的 require 語句
require(['foo', 'bar'], function (foo, bar) {
isReady = true;
foobar = foo() + bar();
});
// 咱們仍能夠返回一個模塊
return {
isReady: isReady,
foobar: foobar
};
});
CMD規範與AMD規範的區別以下:
1. CMD依賴就近:好比以下代碼
define(function(require,exports,module){
var a = require('./a');
a.doSomthing();
});
代碼在運行時,首先是不知道依賴的,須要遍歷全部的require關鍵字,找出後面的依賴。具體作法是將function toString後,用正則匹配出require關鍵字後面的依賴。
而AMD依賴前置:以下代碼:
define(['./a','./b'],function(a,b){
//......
a.doSomthing();
//......
b.doSomthing();
})
代碼在一旦運行到此處,能當即知曉依賴。而無需遍歷整個函數體找到它的依賴,所以性能有所提高,缺點就是開發者必須顯式得指明依賴——這會使得開發工做量變大,好比:當依賴項有n個時候 那麼寫起來比較煩 且容易出錯。不過 RequireJS 從 2.0 開始,也改爲能夠延遲執行(根據寫法不一樣,處理方式不一樣)。
2. 執行順序上:
CMD是延遲執行的,而AMD是提早執行的。
3. api設計角度:
AMD 的 API 默認是一個當多個用,CMD 的 API 嚴格區分,推崇職責單一。好比 AMD 裏,require 分全局 require 和局部 require,都叫 require。CMD 裏,沒有全局 require,而是根據模塊系統的完備性,提供 seajs.use 來實現模塊系統的加載啓動。CMD 裏,每一個 API 都簡單純粹。
轉自:http://www.cnblogs.com/tugenhua0707/p/3507957.html