详细全面的讲解javascript中的export、import
作者:八九燕来
在 JavaScript 中,export
和 import
是 ES6(ECMAScript 2015)引入的模块系统核心语法,用于实现代码的模块化拆分、复用和依赖管理。它们允许将代码分割到不同文件(模块)中,每个模块专注于特定功能,同时通过 export
暴露内容、import
引入依赖,大幅提升了代码的可维护性和可读性。
一、模块的基本概念
一个 JavaScript 文件就是一个模块(module),模块内部的变量、函数、类等默认是私有的,仅在当前模块内可见。若要让其他模块使用这些内容,必须通过 export
显式暴露;其他模块则通过 import
引入这些暴露的内容。
模块的核心特性:
- 自动运行在严格模式(
"use strict"
)下,避免意外全局变量等问题。 - 模块内的顶层
this
是undefined
(非模块脚本中this
指向全局对象)。 - 模块是单例的:同一模块被多次导入时,仅执行一次,后续导入复用第一次的结果。
- 模块加载是异步的,按依赖顺序执行。
二、export:暴露模块内容
export
用于从当前模块向外暴露内容(变量、函数、类等),供其他模块导入。分为两种方式:命名导出(named export)和默认导出(default export)。
1. 命名导出(Named Export)
一个模块可以有多个命名导出,每个导出都有明确的名称,导入时必须使用相同的名称(可重命名)。
语法形式:
直接在声明时导出:
// 导出变量 export const name = "张三"; export let age = 20; export const arr = [1, 2, 3]; // 导出函数 export function sum(a, b) { return a + b; } // 导出类 export class Person { constructor(name) { this.name = name; } }
先声明后集中导出(更推荐,便于维护导出列表):
// 先声明 const name = "张三"; function sum(a, b) { return a + b; } class Person {} // 集中导出(使用对象形式,键是导出名称,值是要导出的内容) export { name, sum, Person };
导出时重命名(避免名称冲突):使用 as
关键字
const name = "张三"; export { name as userName }; // 导出时将 name 重命名为 userName
2. 默认导出(Default Export)
一个模块只能有一个默认导出,通常用于导出模块的“主要内容”(比如一个核心函数或类)。导入时可以自定义名称,无需与导出名称一致。
语法形式:
直接导出(无需名称):
// 导出默认函数 export default function(a, b) { return a + b; } // 导出默认类 export default class { constructor() {} } // 导出默认对象 export default { name: "张三", age: 20 };
先声明后导出(需显式指定 default
):
const mainFunction = () => { /* ... */ }; export default mainFunction; // 默认导出 mainFunction
注意: 默认导出本质上是“名称为 default
的命名导出”,只是语法上简化了。
3. 混合导出
一个模块可以同时包含命名导出和默认导出:
// 命名导出 export const version = "1.0.0"; // 默认导出 export default function core() { /* 核心功能 */ }
三、import:导入模块内容
import
用于从其他模块导入已导出的内容,语法需与对应模块的 export
方式匹配。
1. 导入命名导出的内容
需使用大括号 {}
包裹导出时的名称,且名称必须与导出时一致(可通过 as
重命名)。
基本语法:
// 导入 module.js 中的命名导出 import { name, sum, Person } from './module.js'; // 使用导入的内容 console.log(name); // 张三 console.log(sum(1, 2)); // 3 const p = new Person();
重命名导入(避免冲突):
// 导入时将 sum 重命名为 add import { sum as add } from './module.js'; console.log(add(1, 2)); // 3
2. 导入默认导出的内容
无需大括号,可自定义名称(推荐与模块功能相关的名称)。
基本语法:
// 导入 module.js 的默认导出(假设导出的是一个函数) import calculate from './module.js'; // calculate 是自定义名称 calculate(1, 2); // 调用默认导出的函数
3. 同时导入默认导出和命名导出
// 导入默认导出(core)和命名导出(version) import core, { version } from './module.js'; // 使用 core(); // 调用默认导出的核心函数 console.log(version); // 1.0.0
4. 整体导入(命名空间导入)
将模块中所有导出(包括命名导出和默认导出)作为一个对象的属性导入,默认导出会作为 default
属性。
语法:
// 将 module.js 中所有导出合并为一个 module 对象 import * as module from './module.js'; // 使用命名导出的内容 console.log(module.name); module.sum(1, 2); // 使用默认导出的内容(默认导出会被放在 default 属性中) module.default();
5. 仅执行模块(不导入内容)
如果模块仅需要执行副作用(如初始化操作),无需导入其内容,可直接导入:
import './init.js'; // 执行 init.js 中的代码,但不导入任何内容
四、动态导入(Dynamic Import)
ES2020 引入了动态导入语法 import()
,与静态 import
不同,它是一个函数,返回一个 Promise
,支持在运行时按需加载模块(适合代码分割、懒加载)。
语法:
// 动态导入 module.js,返回 Promise import('./module.js') .then((module) => { // 模块加载成功后使用 console.log(module.name); // 访问命名导出 module.default(); // 访问默认导出 }) .catch((err) => { console.error('模块加载失败', err); });
配合 async/await 使用(更简洁):
async function loadModule() { try { const module = await import('./module.js'); console.log(module.name); } catch (err) { console.error(err); } } loadModule();
应用场景:
- 路由懒加载(如 React Router、Vue Router 中按需加载组件)。
- 根据条件加载不同模块(如不同环境加载不同配置)。
- 减少初始加载资源体积,提升性能。
五、模块路径规则
import
后的模块路径需遵循以下规则:
相对路径:导入本地模块时,必须以 ./
(当前目录)或 ../
(父目录)开头,且通常需要包含文件扩展名(如 .js
)。
import { sum } from './utils/math.js'; // 正确 import { sum } from 'utils/math.js'; // 错误(缺少 ./)
绝对路径:从项目根目录或 CDN 导入(较少用):
import { sum } from '/src/utils/math.js'; // 项目根目录 import { sum } from 'https://cdn.example.com/utils.js'; // CDN
第三方模块:导入 npm 安装的包时,直接写包名(无需路径):
import React from 'react'; // 导入 react 包 import axios from 'axios'; // 导入 axios 包
六、使用环境要求
import
和 export
属于 ES 模块语法,使用时需注意环境支持:
- 浏览器环境:
- 需在
<script>
标签中添加type="module"
属性,声明为模块脚本:
- 需在
<script type="module"> import { sum } from './math.js'; console.log(sum(1, 2)); </script>
- 本地开发时需通过服务器(如
localhost
)访问,直接打开本地文件(file://
协议)会因跨域限制报错。
- 本地开发时需通过服务器(如
- Node.js 环境:
- 默认支持 CommonJS 模块(
require/module.exports
),若使用 ES 模块,需: - 将文件扩展名改为
.mjs
; - 或在
package.json
中添加"type": "module"
。
- 默认支持 CommonJS 模块(
七、常见问题与注意事项
- 默认导出 vs 命名导出:
- 默认导出适合模块的“主要功能”(一个模块一个),导入时名称可自定义。
- 命名导出适合模块的“辅助功能”(多个),导入时名称必须匹配(可重命名)。
- 重复导出:同一名称不能重复命名导出,否则报错。
- 导入不可变:导入的内容是“只读视图”,不能直接修改(但对象属性可改):
// module.js export let count = 0; // 导入后 import { count } from './module.js'; count = 1; // 报错(只读)
- 循环依赖:模块之间循环导入(A 导入 B,B 导入 A)是允许的,但需注意执行顺序可能导致未定义的值。
- 静态分析:静态
import
必须放在模块顶层(不能在if
、函数等块级作用域中),动态import()
则可以。
总结
export
和 import
是 JavaScript 模块化的核心,通过它们可以实现代码的拆分、复用和依赖管理:
export
分为命名导出(多个)和默认导出(一个),用于暴露模块内容。import
需与导出方式匹配,支持命名导入、默认导入、整体导入等。- 动态
import()
支持按需加载,适合性能优化。
掌握这些语法能帮助你写出更清晰、可维护的大型 JavaScript 应用。
到此这篇关于详细全面的解说javascript中的export、import的文章就介绍到这了,更多相关js export、import内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!