ES6
之前,JS一直沒有自己的模塊體系
,這一點對於大型項目的開發很不友好,所以社區出現了CommonJS
和AMD
(本人不熟悉),CommonJS
主要是用於服務器(Node
),AMD
主要是用於瀏覽器
。
但是ES6引入了ESM
,到此,JS終於有了自己的模塊體系
,基本上可以完全取代
CJS和AMD。
下面簡單總結一下ESM
以及ESM和CJS的區別
。
一、CJS
CJS
是 CommonJS
的縮寫。主要用於服務器端,主要使用如下:
// 導出
const obj = {a: 1};
module.exports = obj;
// 引入
const obj = require('./test.js');
二、ESM
ESM是ESModule
,是ECMAScript
自己的模塊體系,是 Javascript
提出的實現一個標准模塊系統的方案,於ES6引入, 代表 ES
模塊。主要使用如下:
// 導出:export命令 export const obj = {name: 'E1e'}; // 默認導出 export default命令 export default {name: 'E1e'}; // 引入接口:import命令 // 引入普通導出 import { obj } from './test.js'; // 引入默認導出 import obj from './test.js';
可以在 HTML
中調用,只要如下
<script type="module"> import {func1} from 'my-lib'; func1(); </script>
在很多現代瀏覽器可以使用
它兼具兩方面的優點:具有 CJS
的簡單語法和 AMD
的異步
三、區別
commonJs 和 esModule 的區別
使用方式不同(以上);CJS
不能在瀏覽器中工作。它必須經過轉換和打包
commonJs是被加載的時候運行,esModule是編譯的時候運行
commonJs輸出的是值的淺拷貝,esModule輸出值的引用
commentJs具有緩存。在第一次被加載時,會完整運行整個文件並輸出一個對象,拷貝(淺拷貝)在內存中。下次加載文件時,直接從內存中取值
commonJs 輸出值拷貝
/*************** a.js**********************/ let count = 0 exports.count = count; // 輸出值的拷貝 exports.add = ()=>{ //這里改變count值,並不會將module.exports對象的count屬性值改變 count++; } /*************** b.js**********************/ const { count, add } = require('./a.js') //在支持es6模塊的環境下等同於 import { count, add } from './a.js' console.log(count) //0 add(); console.log(count)//0
esModule 輸出值引用
/*************** a.js**********************/ export let count = 0;//輸出的是值的引用,指向同一塊內存 export const add = ()=>{ count++;//此時引用指向的內存值發生改變 } /*************** b.js**********************/ import { count, add } from './a.js' console.log(count) //0 add(); console.log(count)//1
ES6 模塊加載 CommonJS 模塊
module.exports 等同於 export default 可以用 import 引入
CommonJS 模塊加載 ES6 模塊
CommonJS 模塊加載 ES6 模塊,不能使用require命令,而要使用import()函數。
exports 和 module.exports 的區別
module.exports 默認值為{}
exports 是 module.exports 的引用
exports 默認指向 module.exports 的內存空間
require() 返回的是 module.exports 而不是 exports
若對 exports 重新賦值,則斷開了 exports 對 module.exports 的指向
引用:
require 和 import 都可引用
module.exports
//foo.js exports.foo="foo" //等同於 module.exports.foo="foo" //bar.js const { foo } = require('./foo.js') console.log(foo);//'foo'
exports
//foo.js exports={ foo: 'foo' } //bar.js const { foo } = require('./foo.js') //reuqire 返回的是 module.exports 對象, 默認為 {} console.log(foo);//undefined
四、其他模式
AMD
AMD
代表異步模塊定義。下面是一個示例代碼
define(['dep1', 'dep2'], function (dep1, dep2) { //Define the module value by returning a value. return function () {}; });
或者
// "simplified CommonJS wrapping" https://requirejs.org/docs/whyamd.html define(function (require) { var dep1 = require('dep1'), dep2 = require('dep2'); return function () {}; });
AMD
是異步(asynchronously
)導入模塊的(因此得名)
一開始被提議的時候,AMD
是為前端而做的(而 CJS
是后端)
AMD
的語法不如 CJS
直觀。我認為 AMD
和 CJS
完全相反
UMD
UMD
代表通用模塊定義(Universal Module Definition
)。
(function (root, factory) { if (typeof define === "function" && define.amd) { define(["jquery", "underscore"], factory); } else if (typeof exports === "object") { module.exports = factory(require("jquery"), require("underscore")); } else { root.Requester = factory(root.$, root._); } }(this, function ($, _) { // this is where I defined my module implementation var Requester = { // ... }; return Requester; }));
在前端和后端都適用(“通用”因此得名)
與 CJS
或 AMD
不同,UMD
更像是一種配置多個模塊系統的模式。
當使用 Rollup/Webpack
之類的打包器時,UMD
通常用作備用模塊