隨着前端技術的不斷髮展,項目愈來愈大,愈來愈很差管理,多人開發越來讓開發者頭疼,因而出現了命名空間,這沒有辦法的辦法,可是全部變量都是全局的話,管理很是混亂,並且在Node 出現前,javascript 在服務器端基本沒有市場,通過javascript 不斷努力,社區爲 javascript 制定了相應的規範。其中 commonJS 規範的提出算是最爲重要的里程碑。
commonJS對模塊的引用很是簡單,主要分爲模塊引用、模塊定義和模塊標示3部分javascript
在模塊中,上下文提供了 require() 方法來引入外來模塊,引入對應的功能。上下文還提供了 exports 對象,用來導出當前模塊的方法或變量。上下文還提供了一個module對象,它表明模塊自己,而 exports 是 module 的屬性。在node中一個文件就是一個模塊,將方法掛載在exports上做爲屬性便可定義導出方式。html
// math.js exports.add = function () { var sum = 0, i = 0, args = arguments, l = args.length; while (i < l) { sum += args[i]; i++ } return sum; }
在commonJS規範中,存在 require() 方法,這個方法接受模塊標示,以此引入一個模塊的API到當前的上下文中。
模塊引入的實例代碼前端
var math = require('math');
模塊標示其實就是傳遞給require()的參數,必須符合小駝峯命名的字符串,或者以.,..開頭的相對路徑,或者絕對路徑。java
CommonJS是主要爲了JS在後端的表現制定的,他是不適合前端的,爲何這麼說呢?
這須要分析一下瀏覽器端的js和服務器端js都主要作了哪些事,有什麼不一樣了:node
服務器端 | 瀏覽器js |
---|---|
加載時從磁盤中加載 | 加載時須要經過網絡加載 |
相同的代碼須要屢次執行 | 代碼須要從一個服務器端分發到多個客戶端執行 |
CPU和內存資源是瓶頸 | 帶寬是瓶頸 |
commonJS在服務器端運行徹底沒有問題的,由於全部資源都在服務器端的磁盤裏,加載速度很快。可是在瀏覽器端由於網速的限制,加載資源須要時間,會阻塞代碼的運行,而AMD(異步模塊定義)的出現,能夠異。它的模塊定義以下:jquery
define(id?, dependencies?, factory);
它的模塊id和依賴都是可選的,而factory函數的內容就是實際代碼內容,假設一個模塊不依賴任何一個模塊後端
//math.js define(function () { var math = {}; math.add = function (arr) { for(var i = 0, sum = 0; i < arr.length; i++) { sum += arr[i]; } return sum; } math.muti = function (arr) { for(var i = 0, sum = 0; i < arr.length; i++) { sum *= arr[i]; } return sum; } })
引用的時候這樣寫瀏覽器
//main.js define(['math', function(math) { var arr = [1, 10, 20], sum = math.add(arr); console.log(sum); //31 }]
固然這是原理,你們明白了以後,對於入門者,估計仍是不知道怎麼去用,那麼我就幫人幫到底(會用的繞過)。服務器
<script src="js/require.js"></script>
若是以爲以爲這個文件加載也會堵塞 js 的話就把他放在代碼的底部,而後這樣寫網絡
<script src="js/require.js" defer async="true" ></script>
其中defer是爲了兼容IE瀏覽器。加載完requirejs以後,怎麼加載咱們本身的js呢
2.加載咱們本身的js
<script src="js/require.js" data-main="path/main"></script>
// main.js // 首先用config()指定各模塊路徑和引用名 require.config({ baseUrl: "js/lib", paths: { "jquery": "jquery.min", //實際路徑爲js/lib/jquery.min.js "underscore": "underscore.min", } }); // 執行基本操做 require(["jquery","underscore"],function($,_){ // some code here });
data-main 屬性裏面的就是咱們本身的入口文件了,因爲 requirejs 默認加載 js 文件的,因此 後綴 js 能夠省略。OK,下面就能夠快樂的寫模塊了。
CMD規範由國內的玉伯大神指出。是另外一種js模塊化方案,它與AMD很相似,不一樣點在於:AMD 推崇依賴前置、提早執行,CMD推崇依賴就近、延遲執行。
/** AMD寫法 **/ define(["a", "b", "c", "d", "e", "f"], function(a, b, c, d, e, f) { // 等於在最前面聲明並初始化了要用到的全部模塊 a.doSomething(); if (false) { // 即使沒用到某個模塊 b,但 b 仍是提早執行了 b.doSomething() } }); /** CMD寫法 **/ define(function(require, exports, module) { var a = require('./a'); //在須要時申明 a.doSomething(); if (false) { var b = require('./b'); b.doSomething(); } }); /** sea.js **/ // 定義模塊 math.js define(function(require, exports, module) { var $ = require('jquery.js'); var add = function(a,b){ return a+b; } exports.add = add; });
require, exports 和 module 經過形參傳遞給模塊,在須要依賴模塊時,隨時引入,能夠看出,與 AMD 規範相比,CMD 規範更加接近 node 對 commonJS規範的定義。
技術在發展,優秀的開源項目也在不斷更新,好比jquery,underscore。它們很快出了兼容不一樣規範的版本,那麼他們是怎麼作到的,是寫好幾套符合不一樣規範的代碼麼,固然不是。那麼咱們怎麼寫出像他們那樣兼容不一樣規範的代碼呢,很簡單,我給出一個例子:
//hello.js ;(function(name, definition){ //檢測上下文環境是否爲 AMD 或 CMD var hasDefine = typeof define === 'function', hasExports = typeof module !== 'undefined' && module.exports; if (hasDefine) { //AMD 環境或 CMD 環境 define(definition); } else if (hasExports) { // 定義爲普通的node模塊 module.exports = definition(); } else { //將模塊的執行結果掛在 window 變量中,在瀏覽器中 this 指向 window 對象 this[name] = definition(); } })('hello', function() { //代碼主體 var hello = function () {}; return hello; })