什么是CommonJs模块和Es Module模块,它们之间有哪些区别?
- 内容介绍
- 文章标签
- 相关推荐
本文共计2959个文字,预计阅读时间需要12分钟。
什么是CommonJS和ES Module?
CommonJS和ES Module是JavaScript模块化编程的两种不同的规范。
CommonJS
- 使用场景:主要适用于服务器端JavaScript开发,也兼容Node.js环境。- 模块定义:通过`require`和`module.exports`实现模块的导入和导出。- 异步加载:模块加载是异步的,即`require`会立即返回模块内容,但实际的加载过程是异步进行的。- 文件格式:通常以`.js`结尾。
ES Module
- 使用场景:主要适用于浏览器端和Node.js环境。- 模块定义:使用`import`和`export`关键字进行模块的导入和导出。- 同步加载:模块加载是同步的,即`import`会阻塞代码执行直到模块加载完成。- 文件格式:通常以`.js`结尾,但也可以是`.mjs`。
区别:
- 加载方式:CommonJS是异步加载,ES Module是同步加载。- 语法:CommonJS使用`require`和`module.exports`,ES Module使用`import`和`export`。- 兼容性:CommonJS不兼容ES Module,需要通过转译工具如Babel进行转换。
下面简要介绍CommonJS和ES Module的用途和区别:
CommonJs
CommonJS是Node.js的模块规范,它允许你通过`require`来导入模块,并通过`module.exports`来导出模块。CommonJS适合服务器端开发,因为它可以异步地加载模块,并且在服务器端环境中通常不需要同步加载模块。
ES Module
ES Module是ECMAScript 2015(ES6)引入的模块规范,它支持静态的模块导入和导出。ES Module在浏览器和Node.js中都有很好的支持,它允许你通过`import`和`export`来导入和导出模块,并且支持动态导入。
为什么会有CommonJS和ES Module?
在JavaScript早期,模块化并不是一个标准特性,不同的环境和库可能使用不同的模块化方式。随着Node.js和ES6的兴起,两种模块规范应运而生,以满足不同环境和需求。
我们为什么需要这两种模块规范?
- 兼容性:不同的环境和库可能使用不同的模块规范,因此需要这两种规范来确保代码在不同环境中都能正常运行。- 灵活性:不同的模块规范提供了不同的功能和特性,可以根据具体需求选择合适的模块规范。- 生态支持:CommonJS和ES Module都有广泛的社区和库支持,可以方便地使用各种模块化的工具和库。
希望以上内容对您有所帮助!如果您有任何进一步的问题,请随时提问。
什么是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中导出分为两种,单个导出(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
- CommonJs可以动态加载语句,代码发生在运行时
- CommonJs混合导出,还是一种语法,只不过不用声明前面对象而已,当我导出引用对象时之前的导出就被覆盖了
- CommonJs导出值是拷贝,可以修改导出的值,这在代码出错时,不好排查引起变量污染
Es Module
Es Module是静态的,不可以动态加载语句,只能声明在该文件的最顶部,代码发生在编译时
Es Module混合导出,单个导出,默认导出,完全互不影响
Es Module导出是引用值之前都存在映射关系,并且值都是可读的,不能修改
谢谢各位在百忙之中点开这篇文章,希望对你们能有所帮助,如有问题欢迎各位大佬指正。
我是蛙人,如果觉得写得可以的话,请点个赞吧。
原文地址:juejin.cn/post/6938581764432461854
作者:蛙人
更多编程相关知识,请访问:编程视频!!
本文共计2959个文字,预计阅读时间需要12分钟。
什么是CommonJS和ES Module?
CommonJS和ES Module是JavaScript模块化编程的两种不同的规范。
CommonJS
- 使用场景:主要适用于服务器端JavaScript开发,也兼容Node.js环境。- 模块定义:通过`require`和`module.exports`实现模块的导入和导出。- 异步加载:模块加载是异步的,即`require`会立即返回模块内容,但实际的加载过程是异步进行的。- 文件格式:通常以`.js`结尾。
ES Module
- 使用场景:主要适用于浏览器端和Node.js环境。- 模块定义:使用`import`和`export`关键字进行模块的导入和导出。- 同步加载:模块加载是同步的,即`import`会阻塞代码执行直到模块加载完成。- 文件格式:通常以`.js`结尾,但也可以是`.mjs`。
区别:
- 加载方式:CommonJS是异步加载,ES Module是同步加载。- 语法:CommonJS使用`require`和`module.exports`,ES Module使用`import`和`export`。- 兼容性:CommonJS不兼容ES Module,需要通过转译工具如Babel进行转换。
下面简要介绍CommonJS和ES Module的用途和区别:
CommonJs
CommonJS是Node.js的模块规范,它允许你通过`require`来导入模块,并通过`module.exports`来导出模块。CommonJS适合服务器端开发,因为它可以异步地加载模块,并且在服务器端环境中通常不需要同步加载模块。
ES Module
ES Module是ECMAScript 2015(ES6)引入的模块规范,它支持静态的模块导入和导出。ES Module在浏览器和Node.js中都有很好的支持,它允许你通过`import`和`export`来导入和导出模块,并且支持动态导入。
为什么会有CommonJS和ES Module?
在JavaScript早期,模块化并不是一个标准特性,不同的环境和库可能使用不同的模块化方式。随着Node.js和ES6的兴起,两种模块规范应运而生,以满足不同环境和需求。
我们为什么需要这两种模块规范?
- 兼容性:不同的环境和库可能使用不同的模块规范,因此需要这两种规范来确保代码在不同环境中都能正常运行。- 灵活性:不同的模块规范提供了不同的功能和特性,可以根据具体需求选择合适的模块规范。- 生态支持:CommonJS和ES Module都有广泛的社区和库支持,可以方便地使用各种模块化的工具和库。
希望以上内容对您有所帮助!如果您有任何进一步的问题,请随时提问。
什么是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中导出分为两种,单个导出(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
- CommonJs可以动态加载语句,代码发生在运行时
- CommonJs混合导出,还是一种语法,只不过不用声明前面对象而已,当我导出引用对象时之前的导出就被覆盖了
- CommonJs导出值是拷贝,可以修改导出的值,这在代码出错时,不好排查引起变量污染
Es Module
Es Module是静态的,不可以动态加载语句,只能声明在该文件的最顶部,代码发生在编译时
Es Module混合导出,单个导出,默认导出,完全互不影响
Es Module导出是引用值之前都存在映射关系,并且值都是可读的,不能修改
谢谢各位在百忙之中点开这篇文章,希望对你们能有所帮助,如有问题欢迎各位大佬指正。
我是蛙人,如果觉得写得可以的话,请点个赞吧。
原文地址:juejin.cn/post/6938581764432461854
作者:蛙人
更多编程相关知识,请访问:编程视频!!

