由CommonJS組織提出了許多新的JavaScript架構方案和標準,但願能爲前端開發提供統一的指引。AMD規範就是其中比較著名一個,全稱是Asynchronous Module Definition,即異步模塊加載機制。完整描述了模塊的定義,依賴關係,引用關係以及加載機制。該規範已被requireJS,NodeJs,Dojo,JQuery使用,能夠看出它具備很大的價值。前端
做爲一個規範,只需定義其語法API,而不關心其實現。AMD規範簡單到只有一個API,即define函數:
define([module-name?], [array-of-dependencies?], [module-factory-or-object]);
其中:
module-name: 模塊標識,能夠省略。
array-of-dependencies: 所依賴的模塊,能夠省略。
module-factory-or-object: 模塊的實現,或者一個JavaScript對象。
define函數具備的另一個性質,異步性。當define函數執行時,
1)首先會異步的去調用第二個參數中列出的依賴模塊
2)當全部的模塊被載入完成以後,若是第三個參數是一個回調函數則執行
3)而後告訴系統模塊可用,也就通知了依賴於本身的模塊本身已經可用。瀏覽器
下面代碼定義了一個alpha模塊,而且依賴於內置的require,exports模塊,以及外部的beta模塊。能夠看到,第三個參數是回調函數,能夠直接使用依賴的模塊,他們按依賴聲明順序做爲參數提供給回調函數。
1)require函數讓你可以隨時去依賴一個模塊,即取得模塊的引用,從而即便模塊沒有做爲參數定義,也可以被使用;
2)exports是定義的alpha 模塊的實體,在其上定義的任何屬性和方法也就是alpha模塊的屬性和方法。經過exports.verb = ...就是爲alpha模塊定義了一個verb方法。
3)例子中是簡單調用了模塊beta的verb方法。架構
define("alpha", ["require", "exports", "beta"], function (require, exports, beta) { exports.verb = function() { return beta.verb(); //或者: return require("beta").verb(); } });
define 方法容許你省略第一個參數,這樣就定義了一個匿名模塊,這時候模塊文件的文件名就是模塊標識。
若是這個模塊文件放在a.js中,那麼a就是模塊名。能夠在依賴項中用"a"來依賴於這個匿名模塊。
好處就是模塊是高度可重用,一個匿名模塊隨便放在一個位置就可使用它,模塊名就是它的文件路徑。
下面的代碼就定義了一個依賴於alpha模塊的匿名模塊:異步
define(["alpha"], function (alpha) { return { verb: function(){ return alpha.verb() + 2; } }; });
define的前兩個參數都是能夠省略的。第三個參數有兩種狀況,一種是一個JavaScript對象,另外一種是一個函數。函數
若是是一個對象,那麼它多是一個包含方法具備功能的一個對象;也有多是僅提供數據。後者和JSON-P很是相似,所以AMD也能夠認爲包含了一個完整的JSON-P實現。模塊演變爲一個簡單的數據對象,這樣的數據對象是高度可用的,並且由於是靜態對象,它也是CDN友好的,能夠提升JSON-P的性能。考慮一個提供中國省市對應關係的JavaScript對象,若是以傳統JSON-P的形式提供給客戶端,它必須提供一個callback函數名,根據這個函數名動態生成返回數據,這使得標準JSON-P數據必定不是CDN友好的。但若是用AMD,這個數據文件就是以下的形式:工具
define({ provinces: [ {name: '上海',areas: ['浦東新區', '徐彙區']}, {name: '江蘇',cities: ['南京', '南通']}
//..... ] });
假設這個文件名爲china.js,那麼若是某個模塊須要這個數據,只須要:性能
define(['china'], function(china){ //在這裏使用中國省市數據 });
經過這種方式,這個模塊是真正高度可複用的,不管是用遠程的,仍是Copy到本地項目,都節約了開發時間和維護時間。ui
若是參數是一個函數,其用途之一是快速開發實現。適用於較小型的應用,你無需提早關注本身須要什麼模塊,本身給誰用。在函數中,能夠隨時require本身須要的模塊。例如:spa
define(function(){ var p = require('china'); //使用china這個模塊 });
即你省略了模塊名,以及本身須要依賴的模塊。這不意味着你無需依賴於其餘模塊,而是可讓你在須要的時候去require這些模塊。define方法在執行的時候,會調用函數的toString方法,並掃描其中的require調用,提早幫助你載入這些模塊,載入完成以後再執行。這使得快速開發成爲可能。code
須要注意的一點是,Opera不能很好的支持函數的toString方法,所以,在瀏覽器中它的適用性並非很強。但若是你是經過build工具打包全部的 JavaScript文件,這將不是問題,構建工具會幫助你掃描require並強制載入依賴的模塊。