每个 js 文件都是一个模块,默认采用的 CommonJS 模块规范

新兴的 ES6 模块 pk 传统的 CommonJS 模块

特性

CommonJS

ES6 模块化

导出

exports 对象

export 关键字

导入

require()函数

import 关键字

加载模式

同步

异步

执行模式

单例

单例

依赖关系

静态

动态

树形摇晃

不支持

支持

加载模式

  • CommonJS 是同步的, 在加载模块之前,代码会停止执行。
  • ES6 模块是异步的,代码可以继续执行,而模块将在稍后加载。

执行模式

CommonJS 和 ES6 模块的执行都是单例的:模块只会被加载一次,并且所有对模块的引用都将指向同一个实例。

依赖关系

  • CommonJS 是静态的, 模块的依赖关系在编译时确定。
  • ES6 模块是动态的,模块的依赖关系在运行时确定

树形摇晃

一种优化技术,用于从 JavaScript 捆绑包中删除未使用的代码。

  • CommonJS 不支持树形摇晃,模块中未使用的代码也会被加载。
  • ES6 模块化支持树形摇晃,可以自动删除未使用的代码,从而减小包的大小。

启用 ES6 模块的三种方法

  1. 在 package.json 文件中设置 "type": "module",这样 Node.js 就会将所有 .js 文件视为 ES6 模块。
  2. 将文件扩展名改为 .mjs,这样 Node.js 会自动将其视为 ES6 模块。
  3. 在 script 标签中添加 type="module" 属性

ES6 模块语法

默认导出导入 export default

每个模块默认的导出只能有一个

let a = 1
// 默认导出 a
export default a
  • 1.
  • 2.
  • 3.
// 导入默认时,可以命其他名称
import b from './demo.js'

console.log(b)
  • 1.
  • 2.
  • 3.
  • 4.

可以直接使用函数表达式/匿名函数作为默认导出

export default function myFunc() {}
  • 1.
export default function() {}。
  • 1.

导出导入多项 export { }

let a = 1
let b = 2

export { a, b }
  • 1.
  • 2.
  • 3.
  • 4.
// 导入多项时,必须与导出名对应
import { a, b } from './demo.js'

console.log(a, b)
  • 1.
  • 2.
  • 3.
  • 4.

导出时重命名 as

let a = 1
let b = 2

export { a as c, b as d }
  • 1.
  • 2.
  • 3.
  • 4.
// 导入时,只能导入新的名称
import { c, d } from './demo.js'

console.log(c, d)
  • 1.
  • 2.
  • 3.
  • 4.

导出其他模块指定项

export { name1, name2, ... } from 'module-name'
  • 1.

导入模块导出的所有内容 import *

export let a = 1;
export let b = 2;
  • 1.
  • 2.
// 通过 as 重命名为一个变量(值为对象)
import * as myModule from "./demo.mjs";

console.log(myModule.a);
console.log(myModule.b);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

导入时重命名 as

import {trunc as StringLib} from "../lib/string.js"
import {trunc as MathLib} from "../lib/math.js"
  • 1.
  • 2.

导入 json 格式的文件

import pkg from "./package.json" assert { type: "json" };
  • 1.
const { default: jsonObject } = await import('./file.json', {
  assert: {
    type: 'json'
  }
});
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

导入 CommonJS 模块

import * as 自定义名称  from '模块名称'
  • 1.

CommonJS 模块语法

  • 每个模块内有一个 module 对象,其有属性 exports(属性值也是一个对象)
  • 通过 require() 导入时,会获取到导出模块中 module 对象的 exports 属性
  • 在同一个模块中,不要混用 exports 和 module.exports 来导出不同的内容,因为这会导致混淆和不可预期的行为。

导出导入单项 module.exports

导出

module.exports = "朝阳";
  • 1.

导入

const demoModule = require("./demo.js");

console.log(demoModule); // 朝阳
  • 1.
  • 2.
  • 3.

导出导入多项 exports

导出

exports.a = 1;
exports.b = 2;
  • 1.
  • 2.

导入

const demoModule = require("./demo.js");

console.log(demoModule); // { a: 1, b: 2 }
  • 1.
  • 2.
  • 3.