ES6 - 模块
ES6 - 模块(import/export)
Section titled “ES6 - 模块(import/export)”ES6 为 JavaScript 引入了一个标准化的模块系统,允许开发者将代码组织成可重用、自包含的单元。模块有助于管理复杂性、提高代码可维护性,并实现更好的依赖管理。
模块本质上是一个 JavaScript 文件。默认情况下,在模块中定义的变量、函数或类是该模块私有的。要使其可从其他模块访问,您必须显式地 export(导出)它们。要在另一个模块中使用导出的实体,您需要 import(导入)它。
export:用于从模块中暴露函数、对象或原始值,以便其他程序/模块可以使用它们。import:用于从另一个模块引入导出的成员。- 严格模式(Strict Mode):模块默认处于严格模式下。
- 作用域(Scope):每个模块都有自己的顶层作用域。在模块中声明的变量不是全局的。
主要有两种类型的导出:命名导出(named exports)和默认导出(default export)。
1. 命名导出
Section titled “1. 命名导出”一个模块可以导出多个命名实体。这些实体可以在声明时导出,或者在文件末尾使用一个 export 语句统一导出。
export const PI = 3.14159;
export function add(a, b) { return a + b;}
export class Calculator { constructor() {} multiply(a, b) { return a * b; }}
// 或者,在文件末尾统一导出:// const PI = 3.14159;// function add(a, b) { ... }// class Calculator { ... }// export { PI, add, Calculator };2. 默认导出
Section titled “2. 默认导出”一个模块最多只能有一个默认导出。它通常用于导出模块提供的主要实体,例如一个类或一个主函数。
export default function logMessage(message) { console.log(`LOG: ${message}`);}
// 或者导出类:// export default class User { ... }您可以在同一个模块中同时拥有命名导出和默认导出。
要使用导出的成员,您需要使用 import 语句。
1. 导入命名导出
Section titled “1. 导入命名导出”使用花括号 {} 来指定要导入哪些命名导出。
import { PI, add, Calculator } from './utils.js';
console.log(PI);console.log(add(5, 3));const calc = new Calculator();console.log(calc.multiply(4, 5));
// 您也可以重命名导入:// import { add as sumNumbers } from './utils.js';// console.log(sumNumbers(10, 2));
// 将所有命名导出作为一个对象导入:// import * as Utils from './utils.js';// console.log(Utils.PI);// console.log(Utils.add(1,1));2. 导入默认导出
Section titled “2. 导入默认导出”您可以为导入的默认实体选择任意名称。
// main.js (续)import myLogger from './logger.js'; // 'myLogger' 可以是任意名称
myLogger('Application started.');3. 同时导入默认导出和命名导出
Section titled “3. 同时导入默认导出和命名导出”// export const version = '1.0';// export default function greet() { console.log('Hello!'); }
// main.js// import greet, { version } from './anotherModule.js';在浏览器中使用 ES 模块
Section titled “在浏览器中使用 ES 模块”要在 Web 浏览器中直接使用 ES 模块,您需要在 <script> 标签中添加 type="module" 属性来告诉浏览器这是一个模块脚本。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>ES Modules Demo</title></head><body> <h1>Check the console for module output!</h1> <!-- main.js 脚本将从 utils.js 和 logger.js 中导入 --> <script type="module" src="main.js"></script></body></html>浏览器模块的重要注意事项:
- 模块脚本默认是延迟执行的(它们在 HTML 解析完成后执行)。
import语句中的路径是相对于导入文件位置的相对路径(例如./utils.js)或绝对 URL。- 通常需要通过 Web 服务器(即使是简单的本地服务器)来提供您的 HTML 文件和 JavaScript 模块,因为在使用
file:///URL 导入模块时会受到 CORS 限制。 - 对于不支持 ES 模块的旧版浏览器,您通常需要使用像 Webpack、Rollup 或 Parcel 这样的打包工具(bundler),以及像 Babel 这样的转译器(transpiler),将 ES 模块转换为旧版浏览器可以理解的格式。
在 Node.js 中使用 ES 模块
Section titled “在 Node.js 中使用 ES 模块”Node.js 支持 ES 模块。主要有两种启用方式:
- 为您的模块文件使用
.mjs文件扩展名。 - 或者,在您的
package.json文件中,添加"type": "module"。这会告诉 Node.js 将该项目中的所有.js文件视为 ES 模块。
package.json 中使用 "type": "module" 的示例:
{ "name": "my-node-app", "version": "1.0.0", "type": "module", "main": "main.js"}然后您的 utils.js、logger.js 和 main.js 文件(如前所述)就可以工作了。您可以使用 node main.js 运行 main.js。
// main.js (Node.js 示例)import fs from 'fs'; // 导入一个内置 Node.js 模块import _ from 'lodash'; // 导入一个第三方包(需要先执行 npm install lodash)
fs.writeFileSync('test.txt', 'Hello from Node.js module!');console.log(_.capitalize('hello world'));动态导入(import())
Section titled “动态导入(import())”ES2020 引入了动态导入,允许您按需加载模块。import() 函数返回一个 Promise 对象。
async function loadUtility() { if (someCondition) { const utilsModule = await import('./utils.js'); utilsModule.add(10, 20); }}这对于代码拆分(code splitting)、条件加载或加载在运行时确定路径的模块非常有用。
模块的优点:
Section titled “模块的优点:”- 组织性:将大型应用程序分解为更小、更易于管理的块。
- 可重用性:代码可以轻松地在应用程序的不同部分或不同项目中重复使用。
- 封装性:隐藏模块的内部实现细节,仅暴露公共 API。
- 依赖管理:清晰地定义代码不同部分之间的依赖关系。