這篇文章帶給大家的內容是關於JavaScript模組規範的CommonJS、AMD和CMD的介紹,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
這篇文章來自對文章《js模組化程式設計之徹底弄清楚CommonJS和AMD/CMD! 》的總結,大部分摘自文章原話,本人只是為了學習方便做的筆記,之後有新的體會會及時補充。如有侵權,聯絡必刪,致敬前輩!
在開始之前,先回答我:為什麼模組很重要?
答:因為有了模組,我們就可以更方便使用別人的程式碼,想要什麼功能,就載入什麼模組。但是,這樣做有一個前提,就是大家必須以同樣的方式寫模組,否則你有你的寫法,我有我的寫法,豈不是亂了套!
於是下面三個模組規範出來了,這篇文章也出來了。事先說明一下,CommonJS規範的實作是node.js,AMD(Asynchronous Module Definition)規範的實作是require.js和curl.js,CMD規範的實作是Sea.js。
JS中的模組規格(CommonJS,AMD,CMD),如果你聽過js模組化這個東西,那麼你就應該聽過或CommonJS或AMD甚至是CMD這些規範咯,我也聽過,但之前也真的是聽聽看而已。現在就看看吧,這些規範到底是啥東西,幹嘛的。本文包括這三個規範的來源及對應的產物的原理。
1.一開始大家都認為JS是辣雞,沒什麼用,官方定義的API只能構建基於瀏覽器的應用程序,逗我呢,這太狹隘了吧(用了個高端詞,嘎嘎),CommonJS就按耐不住了,CommonJS API定義很多普通應用程式(主要指非瀏覽器的應用)使用的API,從而填補了這個空白。它的終極目標是提供一個類似Python,Ruby和Java標準函式庫。這樣的話,開發者可以使用CommonJS API編寫應用程序,然後這些應用可以運行在不同的JavaScript解釋器和不同的主機環境中。
在相容CommonJS的系統中,你可以使用JavaScript開發以下程式:
(1).伺服器端JavaScript應用程式
(2).命令列工具
( 3).圖形介面應用程式
(4).混合應用程式(如,Titanium或Adobe AIR)
2009年,美國程式設計師Ryan Dahl創造了node.js項目,將javascript語言用於伺服器端程式設計。 這標誌"Javascript模組化程式設計"正式誕生。因為老實說,在瀏覽器環境下,沒有模組也不是特別大的問題,畢竟網頁程式的複雜性有限;但是在伺服器端,一定要有模組,與作業系統和其他應用程式互動,否則根本沒辦法編程。 NodeJS是CommonJS規格的實作,webpack 也是以CommonJS的形式來寫字。
node.js的模組系統,就是參考CommonJS規格實現的。在CommonJS中,有一個全域性方法require(),用於載入模組。假定有一個數學模組math.js,就可以像下面這樣載入。
var math = require('math');
然後,就可以呼叫模組提供的方法:
var math = require('math');
math.add(2,3); // 5
CommonJS定義的模組分為:{模組引用(require)} {模組定義(exports)} {模組識別(module)}
require()用來引入外部模組;exports對象用於導出目前模組的方法或變量,唯一的導出口;module物件就代表模組本身。
雖然說Node遵循CommonJS的規範,但相比也是做了一些取捨,填了一些新東西的。
不過,我說了CommonJS也說了Node,那我覺得也得先了解下NPM了。 NPM作為Node的套件管理器,不是為了幫助Node解決依賴套件的安裝問題嘛,那它肯定也要遵循CommonJS規範啦,它遵循套件規範(還是理論)的。 CommonJS WIKI講了它的歷史,也介紹了modules和packages等。
下面講commonJS的原理以及簡易實作:
1、原理
瀏覽器不相容CommonJS的根本原因,在於缺少四個Node.js環境的變數。
module exports require global
只要能提供這四個變量,瀏覽器就能載入 CommonJS 模組。
下面是一個簡單的範例。
var module = { exports: {} }; (function(module, exports) { exports.multiply = function (n) { return n * 1000 }; }(module, module.exports)) var f = module.exports.multiply; f(5) // 5000
上面程式碼向一個立即執行函數提供 module 和 exports 兩個外部變量,模組就放在這個立即執行函數裡面。模組的輸出值放在 module.exports 之中,這樣就實作了模組的載入。
基於commonJS規範的nodeJS出來以後,服務端的模組概念已經形成,很自然地,大家就想要客戶端模組。而且最好兩者能夠相容,一個模組不用修改,在伺服器和瀏覽器都可以運作。但是,由於一個重大的限制,使得CommonJS規格不適用於瀏覽器環境。還是上面的程式碼,如果在瀏覽器中運行,會有一個很大的問題,你能看出來嗎?
var math = require('math'); math.add(2, 3);
第二行math.add(2, 3),在第一行require('math')之后运行,因此必须等math.js加载完成。也就是说,如果加载时间很长,整个应用就会停在那里等。您会注意到 require 是同步的。
这对服务器端不是一个问题,因为所有的模块都存放在本地硬盘,可以同步加载完成,等待时间就是硬盘的读取时间。但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于"假死"状态。
因此,浏览器端的模块,不能采用"同步加载"(synchronous),只能采用"异步加载"(asynchronous)。这就是AMD规范诞生的背景。
CommonJS是主要为了JS在后端的表现制定的,他是不适合前端的,AMD(异步模块定义)出现了,它就主要为前端JS的表现制定规范。
AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。
AMD也采用require()语句加载模块,但是不同于CommonJS,它要求两个参数:
require([module], callback);
第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。如果将前面的代码改写成AMD形式,就是下面这样:
require(['math'], function (math) { math.add(2, 3); });
math.add()与math模块加载不是同步的,浏览器不会发生假死。所以很显然,AMD比较适合浏览器环境。目前,主要有两个Javascript库实现了AMD规范:require.js和curl.js。
Require.js主要提供define和require两个方法来进行模块化编程,前者用来定义模块,后者用来调用模块。RequireJS就是实现了AMD规范的呢。
大名远扬的玉伯写了seajs,就是遵循他提出的CMD规范,与AMD蛮相近的,不过用起来感觉更加方便些,最重要的是中文版,应有尽有:seajs官方doc
define(function(require,exports,module){...});
前面说AMD,说RequireJS实现了AMD,CMD看起来与AMD好像呀,那RequireJS与SeaJS像不像呢?虽然CMD与AMD蛮像的,但区别还是挺明显的,官方非官方都有阐述和理解,我觉得吧,说的都挺好
以上是JavaScript模組規範的CommonJS、AMD和CMD的介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!