JavaScript 模块导入方式对比


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 = 1export 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); // 使用默认导出

常见问题与注意事项

  1. 默认导出的唯一性

一个模块只能有一个 export default,但可以有多个命名导出。

  1. 避免混淆默认导出与命名导出
  • 若模块只有默认导出,命名空间导入后必须通过 api.default 访问,容易出错。

  • 建议:仅在需要多导出时使用命名空间导入,否则优先用默认导入。

  1. Tree-Shaking 优化

命名空间导入(import * as api)可能会导致打包工具无法进行 Tree-Shaking(删除未使用的代码),而默认导入或按需命名导入(import { a } from '模块')更利于优化。

总结

  • 默认导入:简洁高效,直接获取模块的核心默认导出,适合单一功能模块。

  • 命名空间导入:全面收集所有导出,适合多功能模块,但需注意默认导出在 api.default 中的层级。

根据模块的导出设计和实际使用需求选择合适的导入方式,可提高代码可读性和效率。


文章作者: 弈心
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 弈心 !
评论
  目录