ES Module和CommonJS Module导入导出区别与实践

452 阅读2分钟

ES Module和CommonJS Moudle是什么?

ES Module和CommonJs都是一种Javascript的模块规范,一些不同的库遵循了不同的模范,如vue遵循ES Module规范,express遵循CommonJS规范。

ES Module和CommonJS导入和导出有什么区别

nodejs支持ES Module和CommonJs模块。当遇到.mjs时会按照ES Module规范去解析文件,遇到.cjs文件时会按照CommonJs规范来解析文件。下面我们通过nodejs来看看ES Module和Common Js规范导出和引入的区别。

CommonJS

CommonJS导出

Commonjs使用module.exportsexports进行导出,其中exports为module.exports的引用。如

// a.cjs
module.exports = {
 content: 'I am a Obj from acjs'
}

或者

// a.cjs
exports.content = "I am a Obj from acjs"

使用exports不可以直接指定对象

因为exports是module.exports的引用,将其指向新对象后,其就失去了联系,如下面代码会被忽视

// a.cjs
exports = {
 content: 'I am a Obj from acjs'
}

当我们在其他地方引入a.cjs的时候会得到一个空对象,如

// b.cjs
let aObj = require('./a.cjs');
console.log(aObj); // {} 

CommonJs导入

如上例子,CommonJs使用reuqire()方法来实现导入并接收对象。

ES Module

ES Module导出

ES Module导出使用export关键字,一个模块允许有多个"命名导出",但只允许有一个默认导出。其中命名导出指的是export后直接跟函数或者变量的定义。export default为默认导出。如

// c.mjs
export const c = 'I am a const',d='I am a const,too';
export function aFun(){
 console.log('I am a fun');
}
export default { content: 'I am a default export'}

ES Module导入

ES Module使用import关键字进行导入,其规则如下

  1. 导入由export导出的对象时,语法为import { xxx } from "路径"
  2. 导入由export default导出的对象时,可以去掉花括号,如import xxx from "路径",此处的xxx为自定义名称
  3. import {xxx} from "路径"也可以使用as关键字来自定义名称,如 import {aaa as bbb} from "路径"
import c, { anotherObj , aFun as cFun} from './c.mjs'
console.log(c);
console.log(anotherObj);
console.log(cFun)

关于CommonJs和ESModule多次导出以及导出是否为同一对象问题

我的实践结果为,多次导入同一.cjs或者.mjs文件,对应的文件代码都只执行一次,并且导出的为对象的引用。和网上的说法有些出入。下面贴出实验截图,如有错误,烦请指出

cjs

image.png

image.png

image.png

image.png

可以看到b.cjs和main.cjs都引入了a.cjs,但a.cjs中的代码只被运行了一次,且关于对象类型,导出的为对象类型的引用。

mjs

mjs情况类似

image.png

image.png

image.png

image.png