CommonJs和EsModule的差别

原创
小哥 3年前 (2022-11-08) 阅读数 115 #大杂烩

为什么会有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 = "蛙人"
export.sex = "male"
exports = {
    name: "蛙人"
}

上面example这种情况会更改对象的参考值,因此最后一次导出只是一个对象。

混合导出

混合出口, 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 }

重复导入

不管是 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 sex = "male"
export sex

// 如果有多个
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导出引用值之前存在映射关系,并且这些值是可读的,不能修改。

版权声明

所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除