什麼是CommonJs和Es Module?有什麼區別?以下這篇文章跟大家聊聊什麼是CommonJs和Es Module及它們的差別,希望對大家有幫助!
為什麼會有CommonJs和Es Module呢
我們都知道在早期JavaScript
模組這一概念,都是透過script
標籤引入js
檔案程式碼。當然這寫基本簡單需求沒有什麼問題,但當我們的專案越來越龐大時,我們引入的js
檔案就會越多,這時就會出現以下問題:
- js檔案作用域都是頂層,這會造成變數污染
- js檔案多,變得不好維護
- js檔案依賴問題,稍微不注意順序引入錯,程式碼全報錯誤
為了解決上述問題JavaScript
社群出現了CommonJs
,CommonJs
是一種模組化的規範,包括現在的NodeJs
裡面也採用了部分CommonJs
文法在裡面。那麼在後來Es6
版本正式加入了Es Module
模組,這兩種都是解決上面問題,那麼都是解決什麼問題呢。
- 解決變數污染問題,每個檔案都是獨立的作用域,所以不存在變數污染
- 解決程式碼維護問題,一個檔案裡程式碼非常清晰
- 解決檔案依賴問題,一個檔案裡可以清楚的看到依賴了那些其它檔案
那麼我們下面來一一了解它們的語法及弊端吧
CommonJs 基本語法
匯出
CommonJs
中使用 module.exports
匯出變數及函數,也可以匯出任意型別的值,看如下案例。
// 导出一个对象 module.exports = { name: "蛙人", age: 24, sex: "male" } // 导出任意值 module.exports.name = "蛙人" module.exports.sex = null module.exports.age = undefined
直接匯出
匯出也可以省略module
關鍵字,直接寫exports匯出也可以,看如下案例。
exports.name = "蛙人" exports.sex = "male"
注意:如果使用exports匯出單一值之後,就無法在匯出物件值,這只會修改exports的物件改變,然而修改無效,最終匯出還是name,和sex,因為最終的導出是由module.exports決定的。
exports.name = "蛙人" exports.sex = "male" exports = { name: "蛙人" }
上面example中,這種情況會改變物件的參考值則匯出無效,所以最後匯出的還是name
,sex
。
混合導出
混合導出,exports
和module.exports
可以同時使用,不會有問題。
exports.name = "蛙人" module.exports.age = 24
導入
CommonJs
中使用require
語法可以匯入,如果想要單個的值,可以透過解構物件來取得。
// index.js module.exports.name = "蛙人" module.exports.age = 24 let data = require("./index.js") console.log(data) // { name: "蛙人", age: 24 }
重複導入
不管是CommonJs
或Es Module
都不會重複導入,就是只要該檔案內加載過一次這個文件了,我再次導入一次是不會生效的。
let data = require("./index.js") let data = require("./index.js") // 不会在执行了
動態導入
CommonJs
支援動態導入,什麼意思呢,就是可以在語句中,使用require
文法,來看如下案例。
let lists = ["./index.js", "./config.js"] lists.forEach((url) => require(url)) // 动态导入 if (lists.length) { require(lists[0]) // 动态导入 }
導入值的變化
CommonJs
導入的值是拷貝的,所以可以修改拷貝值,但這會造成變數污染,一不小心就重名。
// index.js let num = 0; module.exports = { num, add() { ++ num } } let { num, add } = require("./index.js") console.log(num) // 0 add() console.log(num) // 0 num = 10
上面example中,可以看到exports
匯出的值是值的拷貝,更改完 num
值沒有變化,並且匯入的num
的值我們也可以進行修改
總結
#CommonJs
解決了變數污染,檔案依賴等問題,上面我們也介紹了它的基本語法,它可以動態導入(程式碼發生在運行時),不可以重複導入。
Es Module 基本語法
#導出
在Es Module
中導出分為兩種,單一導出(export
)、預設導出(export default
),單一導出在導入時不像CommonJs
一樣直接把值全部導入進來了,Es Module
中可以導入我想要的值。那麼預設導出就是全部直接匯入進來,當然Es Module
中也可以匯出任意類型的值。
// 导出变量 export const name = "蛙人" export const age = 24 // 导出函数也可以 export function fn() {} export const test = () => {} // 如果有多个的话 const name = "蛙人" const sex = "male" export { name, sex }
混合導出
可以使用export
和export default
同時使用且互不影響,只需要在匯入時地方注意,如果檔案裡有混合導入,則必須先導入預設導出的,在導入單一導入的值。
export const name = "蛙人" export const age = 24 export default { fn() {}, msg: "hello 蛙人" }
導入
#Es Module
使用的是import
语法进行导入。如果要单个导入则必须使用花括号{}
,注意:这里的花括号跟解构不一样。
// index,js export const name = "蛙人" export const age = 24 import { name, age } from './index.js' console.log(name, age) // "蛙人" 24 // 如果里面全是单个导出,我们就想全部直接导入则可以这样写 import * as all from './index.js' console.log(all) // {name: "蛙人", age: 24}
混合导入
混合导入,则该文件内用到混合导入,import
语句必须先是默认导出,后面再是单个导出,顺序一定要正确否则报错。
// index,js export const name = "蛙人" export const age = 24 export default { msg: "蛙人" } import msg, { name, age } from './index.js' console.log(msg) // { msg: "蛙人" }
上面example中,如果导入的名称不想跟原本地名称一样,则可以起别名。
// index,js export const name = "蛙人" export const age = 24 export default { msg: "蛙人" } import { default as all, name, age } from './index.js' console.log(all) // { msg: "蛙人" }
导入值的变化
export
导出的值是值的引用,并且内部有映射关系,这是export
关键字的作用。而且导入的值,不能进行修改也就是只读状态。
// index.js export let num = 0; export function add() { ++ num } import { num, add } from "./index.js" console.log(num) // 0 add() console.log(num) // 1 num = 10 // 抛出错误
Es Module是静态
就是Es Module
语句``import只能声明在该文件的最顶部,不能动态加载语句,
Es Module`语句运行在代码编译时。
if (true) { import xxx from 'XXX' // 报错 }
总结
Es Module
也是解决了变量污染问题,依赖顺序问题,Es Module
语法也是更加灵活,导出值也都是导出的引用,导出变量是可读状态,这加强了代码可读性。
CommonJs和Es Module的区别
CommonJs
- CommonJs可以动态加载语句,代码发生在运行时
- CommonJs混合导出,还是一种语法,只不过不用声明前面对象而已,当我导出引用对象时之前的导出就被覆盖了
- CommonJs导出值是拷贝,可以修改导出的值,这在代码出错时,不好排查引起变量污染
Es Module
Es Module是静态的,不可以动态加载语句,只能声明在该文件的最顶部,代码发生在编译时
Es Module混合导出,单个导出,默认导出,完全互不影响
Es Module导出是引用值之前都存在映射关系,并且值都是可读的,不能修改
感谢
谢谢各位在百忙之中点开这篇文章,希望对你们能有所帮助,如有问题欢迎各位大佬指正。
我是蛙人,如果觉得写得可以的话,请点个赞吧。
原文地址:https://juejin.cn/post/6938581764432461854
作者:蛙人
更多编程相关知识,请访问:编程视频!!
以上是淺析什麼是CommonJs和Es Module?有什麼區別?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

記事本++7.3.1
好用且免費的程式碼編輯器

WebStorm Mac版
好用的JavaScript開發工具

Dreamweaver Mac版
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)