首頁 >web前端 >js教程 >淺析什麼是CommonJs和Es Module?有什麼區別?

淺析什麼是CommonJs和Es Module?有什麼區別?

青灯夜游
青灯夜游轉載
2021-10-08 10:17:262820瀏覽

什麼是CommonJs和Es Module?有什麼區別?以下這篇文章跟大家聊聊什麼是CommonJs和Es Module及它們的差別,希望對大家有幫助!

淺析什麼是CommonJs和Es Module?有什麼區別?

為什麼會有CommonJs和Es Module呢

我們都知道在早期JavaScript模組這一概念,都是透過script標籤引入js檔案程式碼。當然這寫基本簡單需求沒有什麼問題,但當我們的專案越來越龐大時,我們引入的js檔案就會越多,這時就會出現以下問題:

  • js檔案作用域都是頂層,這會造成變數污染
  • js檔案多,變得不好維護
  • js檔案依賴問題,稍微不注意順序引入錯,程式碼全報錯誤

為了解決上述問題JavaScript社群出現了CommonJsCommonJs是一種模組化的規範,包括現在的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中,這種情況會改變物件的參考值則匯出無效,所以最後匯出的還是namesex

混合導出

混合導出,exportsmodule.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 }

重複導入

不管是CommonJsEs 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 }

混合導出

可以使用exportexport 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中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除