ESModule、commonJS

109 阅读4分钟

软件中的模块开发:一个功能就是一个模块,多个模块可以组成完整应用,抽离一个模块不会影响其他功能的运行。

commonJS

CommonJS:它是一个致力于将 JavaScript 生态系统标准化的一个组织,它最出名的一个提议就是我们众所周知的 CommonJS modules ,Node 则是在本规范的基础上构建了他自己的模块系统,并且添加了一些自定义扩展。

  • CommonJS定义的模块分为: 模块标识(module)模块定义(exports)模块引用(require)
  • 模块内部可以使用exports对象进行成员导出, 使用require()方法导入其他模块

image.png

导出

exports是module.exports的一个引用,辅助后者添加内容用的。exports指向的是module.exports,也就是说exports的方法module.exports也是一定能完成的。

exports是moudle.exports的一个引用。
exports和module.exports的区别在于,每个模块都有一个module对象,module对象中有一个exports对象,可以把需要导出的成员都挂载到module.exports接口对象中,也就是module.exports.xxx=xxx的方式。
但是每次都这样书写太麻烦,所以nodejs为了更加方便,同时在每一个模块提供了一个成员叫exports,令 exports===module.exports 结果为true ,所以对于 module.exports的方式完全可以使用exports.xxx=xxx 。

// nodejs内部
exports = module.exports

console.log(exports, module.exports) // {}, {}
console.log(exports === module.exports) // true
// 导出一个对象 
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"

混合导出

混合导出,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") // 不会在执行了

动态导入

let lists = ["./index.js", "./config.js"]
lists.forEach((url) => require(url)) // 动态导入

if (lists.length) {
    require(lists[0]) // 动态导入
}

导入值的变化

exports导出的值是值的拷贝,更改完++ num值没有发生变化,并且导入的num的值我们也可以进行修改。

// 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

ESModule

导出

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 蛙人"
}

导入

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 // 抛出错误

不能进行动态导入

export-mdn

import-mdn

nodejs-commonjs

聊聊什么是CommonJs和Es Module及它们的区别