Javascript 中的 CJS, AMD, UMD 和 ESM是什么


ES6之前,JS一直沒有自己的模塊體系,這一點對於大型項目的開發很不友好,所以社區出現了CommonJSAMD(本人不熟悉),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 通常用作備用模塊


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM