JS模組規範:AMD、UMD、CMD、commonJS、ES6 module

NO IMAGE

commonJS

特點:

1、模組可以多次載入,但是只會在第一次載入時執行一次,然後執行結果就被快取了,以後再載入,就直接讀取快取結果。要想讓模組再次執行,必須清除快取。
2、模組載入會阻塞接下來程式碼的執行,需要等到模組載入完成才能繼續執行——同步載入。

環境:伺服器環境
應用:nodejs的模組規範是參照commonJS實現的。
語法:

1、匯入:require(‘路徑’)
2、匯出:module.exports和exports

注意:module.exports和exports的的區別是exports只是對module.exports的一個引用,相當於Node為每個模組提供一個exports變數,指向module.exports。這等同在每個模組頭部,有一行var exports = module.exports;

AMD

特點:

1、非同步載入
2、管理模組之間的依賴性,便於程式碼的編寫和維護。

環境:瀏覽器環境
應用:requireJS是參照AMD規範實現的
語法:

1、匯入:require([‘模組名稱’], function (‘模組變數引用’){// 程式碼});
3、匯出:define(function (){return ‘值’);

demo

// a.js
define(function (){
  return {
   a:'hello world'
  }
});
// b.js
require(['./a.js'], function (moduleA){
console.log(moduleA.a); // 列印出:hello world
});

CMD

特點

1、CMD是在AMD基礎上改進的一種規範,和AMD不同在於對依賴模組的執行時機處理不同,CMD是就近依賴,而AMD是前置依賴。

環境:瀏覽器環境
應用:seajs是參照UMD規範實現的,requireJS的最新的幾個版本也是部分參照了UMD規範的實現
語法:

1、匯入:define(function(require, exports, module) {});
2、匯出:define(function (){return ‘值’);

demo

// a.js
define(function (require, exports, module){
  exports.a = 'hello world';
});
// b.js
define(function (require, exports, module){
var moduleA = require('./a.js');
console.log(moduleA.a); // 列印出:hello world
});

UMD

特點:

1、相容AMD和commonJS規範的同時,還相容全域性引用的方式

環境:瀏覽器或伺服器環境
應用:無
語法:

1、無匯入匯出規範,只有如下的一個常規寫法:

常規寫法:

(function (root, factory) {
if (typeof define === 'function' && define.amd) {
//AMD
define(['jquery'], factory);
} else if (typeof exports === 'object') {
//Node, CommonJS之類的
module.exports = factory(require('jquery'));
} else {
//瀏覽器全域性變數(root 即 window)
root.returnExports = factory(root.jQuery);
}
}(this, function ($) {
//方法
function myFunc(){};
//暴露公共方法
return myFunc;
}));

ES6 module

特點:

1、按需載入(編譯時載入)
2、import和export命令只能在模組的頂層,不能在程式碼塊之中(如:if語句中),import()語句可以在程式碼塊中實現非同步動態按需動態載入

環境:瀏覽器或伺服器環境(以後可能支援)
應用:ES6的最新語法支援規範
語法:

1、匯入:import {模組名A,模組名B…} from ‘模組路徑’
2、匯出:export和export default
3、import(‘模組路徑’).then()方法

注意:export只支援物件形式匯出,不支援值的匯出,export default命令用於指定模組的預設輸出,只支援值匯出,但是隻能指定一個,本質上它就是輸出一個叫做default的變數或方法。
規範:

/*錯誤的寫法*/
// 寫法一
export 1;
// 寫法二
var m = 1;
export m;
// 寫法三
if (x === 2) {
import MyModual from './myModual';
}
/*正確的三種寫法*/
// 寫法一
export var m = 1;
// 寫法二
var m = 1;
export {m};
// 寫法三
var n = 1;
export {n as m};
// 寫法四
var n = 1;
export default n;
// 寫法五
if (true) {
import('./myModule.js')
.then(({export1, export2}) => {
// ...·
});
}
// 寫法六
Promise.all([
import('./module1.js'),
import('./module2.js'),
import('./module3.js'),
])
.then(([module1, module2, module3]) => {
···
});