JavaScript 模块导入方式:默认导入 vs 命名空间导入
概述
在 JavaScript/TypeScript 模块系统中,import api from '模块'(默认导入)和 import * as api from '模块'(命名空间导入)是两种常用的导入方式,它们在导入内容、访问方式和适用场景上存在显著差异。本文档将详细对比这两种方式,帮助开发者正确选择和使用。
核心区别总览
| 维度 | 默认导入 import api from '模块' |
命名空间导入 import * as api from '模块' |
|---|---|---|
| 导入内容 | 仅导入模块的「默认导出」(export default) |
导入模块的「所有导出」(包括默认导出和所有命名导出) |
| 语法本质 | 语法糖,等价于 import { default as api } from '模块' |
收集所有导出成员到一个命名空间对象中 |
| 访问方式 | 直接通过 api.成员 访问 |
通过 api.命名成员 访问命名导出,通过 api.default 访问默认导出 |
| 适用场景 | 仅需要模块的默认导出内容 | 需要同时使用模块的多个命名导出和默认导出 |
详细对比
1. 导入内容范围
默认导入(import api from '模块')
仅关注模块中通过
export default导出的内容(一个对象、函数或类)。忽略模块中的其他命名导出(如果存在)。
命名空间导入(import * as api from '模块')
导入模块中所有的导出成员,包括:
所有命名导出(
export const a = 1、export function b() {}等)。默认导出(会被包装为
api.default属性)。
2. 模块导出与导入后的结构关系
假设存在模块 utils.js,导出内容如下:
// utils.js
const tool = {
version: "1.0.0",
run: () => console.log("运行工具"),
};
// 默认导出
export default tool;
// 命名导出(可选)
export const author = "dev-team";
export function help() {
return "帮助信息";
}
情况 1:使用默认导入
import api from "./utils.js";
// api 直接指向默认导出的 tool 对象
console.log(api.version); // 输出:"1.0.0"(直接访问默认导出的属性)
api.run(); // 输出:"运行工具"(直接调用默认导出的方法)
// 无法访问命名导出(author 和 help 被忽略)
console.log(api.author); // 输出:undefined
情况 2:使用命名空间导入
import * as api from "./utils.js";
// 命名导出的成员直接挂载在 api 上
console.log(api.author); // 输出:"dev-team"
console.log(api.help()); // 输出:"帮助信息"
// 默认导出的成员被放在 api.default 中
console.log(api.default.version); // 输出:"1.0.0"
api.default.run(); // 输出:"运行工具"
3. 典型使用场景
推荐使用默认导入的场景
- 模块仅提供一个核心功能(如工具集对象、主类),且通过
export default导出。 - 你只需要使用模块的默认导出内容,无需关注其他命名导出。
示例(工具集模块):
// 模块:wasm-utils.js
export default {
createPlayer: () => {},
loadFile: () => {},
};
// 导入方
import wasm from "./wasm-utils.js";
wasm.createPlayer(); // 直接使用,简洁直观
推荐使用命名空间导入的场景
- 模块包含多个独立的命名导出(如工具函数集合),需要按需使用其中部分成员。
- 需要同时访问模块的默认导出和命名导出。
示例(多工具模块):
// 模块:format-utils.js
export function formatDate() {}
export function formatNumber() {}
export default {
version: "2.0.0",
};
// 导入方
import * as formatter from "./format-utils.js";
formatter.formatDate(); // 使用命名导出
console.log(formatter.default.version); // 使用默认导出
常见问题与注意事项
- 默认导出的唯一性
一个模块只能有一个 export default,但可以有多个命名导出。
- 避免混淆默认导出与命名导出
若模块只有默认导出,命名空间导入后必须通过
api.default访问,容易出错。建议:仅在需要多导出时使用命名空间导入,否则优先用默认导入。
- Tree-Shaking 优化
命名空间导入(import * as api)可能会导致打包工具无法进行 Tree-Shaking(删除未使用的代码),而默认导入或按需命名导入(import { a } from '模块')更利于优化。
总结
默认导入:简洁高效,直接获取模块的核心默认导出,适合单一功能模块。
命名空间导入:全面收集所有导出,适合多功能模块,但需注意默认导出在
api.default中的层级。
根据模块的导出设计和实际使用需求选择合适的导入方式,可提高代码可读性和效率。