再次梳理AMD、CMD、CommonJS、ES6 Module的區別

前言

回想起以前的一次面試,第一輪面試官問我AMD和CMD的區別,我只回答說AMD是提早加載,CMD是按需加載。第二輪面試官又問了我CommonJS和ES6 Module的區別,emmm...,我大體回答說新的比舊的好~~,雖然面試官並無說什麼,不過顯然這樣的答案並非有助於面試、有助於本身的技術積累的。javascript

因此有必要進行一次梳理,以便更清晰地瞭解它們的特色及差別。css

AMD

AMD一開始是CommonJS規範中的一個草案,全稱是Asynchronous Module Definition,即異步模塊加載機制。後來由該草案的做者以RequireJS實現了AMD規範,因此通常說AMD也是指RequireJS。java

RequireJS的基本用法

經過define來定義一個模塊,使用require能夠導入定義的模塊。jquery

//a.js
//define能夠傳入三個參數,分別是字符串-模塊名、數組-依賴模塊、函數-回調函數
define(function(){
    return 1;
})

// b.js
//數組中聲明須要加載的模塊,能夠是模塊名、js文件路徑
require(['a'], function(a){
    console.log(a);// 1
});
複製代碼

RequireJS的特色

對於依賴的模塊,AMD推崇依賴前置,提早執行。也就是說,在define方法裏傳入的依賴模塊(數組),會在一開始就下載並執行。webpack

CMD

CMD是SeaJS在推廣過程當中生產的對模塊定義的規範,在Web瀏覽器端的模塊加載器中,SeaJS與RequireJS並稱,SeaJS做者爲阿里的玉伯。web

SeaJS的基本用法

//a.js
/* * define 接受 factory 參數,factory 能夠是一個函數,也能夠是一個對象或字符串, * factory 爲對象、字符串時,表示模塊的接口就是該對象、字符串。 * define 也能夠接受兩個以上參數。字符串 id 表示模塊標識,數組 deps 是模塊依賴. */
define(function(require, exports, module) {
  var $ = require('jquery');

  exports.setColor = function() {
    $('body').css('color','#333');
  };
});

//b.js
//數組中聲明須要加載的模塊,能夠是模塊名、js文件路徑
seajs.use(['a'], function(a) {
  $('#el').click(a.setColor);
});
複製代碼

SeaJS的特色

對於依賴的模塊,CMD推崇依賴就近,延遲執行。也就是說,只有到require時依賴模塊才執行。面試

CommonJS

CommonJS規範爲CommonJS小組所提出,目的是彌補JavaScript在服務器端缺乏模塊化機制,NodeJS、webpack都是基於該規範來實現的。數組

CommonJS的基本用法

//a.js
module.exports = function () {
  console.log("hello world")
}

//b.js
var a = require('./a');

a();//"hello world"

//或者

//a2.js
exports.num = 1;
exports.obj = {xx: 2};

//b2.js
var a2 = require('./a2');

console.log(a2);//{ num: 1, obj: { xx: 2 } }
複製代碼

CommonJS的特色

  • 全部代碼都運行在模塊做用域,不會污染全局做用域;
  • 模塊是同步加載的,即只有加載完成,才能執行後面的操做;
  • 模塊在首次執行後就會緩存,再次加載只返回緩存結果,若是想要再次執行,可清除緩存;
  • CommonJS輸出是值的拷貝(即,require返回的值是被輸出的值的拷貝,模塊內部的變化也不會影響這個值)。

ES6 Module

ES6 Module是ES6中規定的模塊體系,相比上面提到的規範, ES6 Module有更多的優點,有望成爲瀏覽器和服務器通用的模塊解決方案。瀏覽器

ES6 Module的基本用法

//a.js
var name = 'lin';
var age = 13;
var job = 'ninja';

export { name, age, job};

//b.js
import { name, age, job} from './a.js';

console.log(name, age, job);// lin 13 ninja

//或者

//a2.js
export default function () {
  console.log('default ');
}

//b2.js
import customName from './a2.js';
customName(); // 'default'
複製代碼

ES6 Module的特色(對比CommonJS)

  • CommonJS模塊是運行時加載,ES6 Module是編譯時輸出接口;
  • CommonJS加載的是整個模塊,將全部的接口所有加載進來,ES6 Module能夠單獨加載其中的某個接口;
  • CommonJS輸出是值的拷貝,ES6 Module輸出的是值的引用,被輸出模塊的內部的改變會影響引用的改變;
  • CommonJS this指向當前模塊,ES6 Module this指向undefined;

目前瀏覽器對ES6 Module兼容還不太好,咱們平時在webpack中使用的export/import,會被打包爲exports/require緩存

寫在後面

這裏比較寬泛地把JavaScript中的幾大模塊化規範列舉出來,但願藉此對JavaScript模塊化有大體的認識,而未對細節展開具體分析,感興趣的能夠自行探索。

相關文章
相關標籤/搜索