ES Module 执行上下文中 export default 与 具名导出

作者:袖梨 2026-06-18
export default 是模块的特殊默认导出入口,不创建变量绑定,仅支持声明或表达式;具名导出则建立对已声明标识符的静态只读绑定,导入需严格匹配名称。

export default 和具名导出(named export)在 ES Module 中行为不同,核心差异不在“值怎么传”,而在“绑定怎么建”和“导入时怎么用”。

export default 是语法糖,不是变量声明

它不创建名为 default 的变量,而是为模块设置一个特殊的默认导出入口。比如:

export default function greet() { return 'hi'; }
等价于内部生成一个隐式绑定(如 __default__),再标记该绑定为 default 导出项。这个函数本身没有名字绑定到当前作用域——它只是被设为模块的默认出口。

因此你不能写:
export default const x = 1;(语法错误)
也不能写:
export default let y = 2;(同样非法)
只能导出声明(函数、类)或表达式(对象字面量、箭头函数等)。

具名导出绑定的是标识符,且必须已声明

所有具名导出都必须引用模块顶层已存在的声明,比如:

  • const a = 1; export { a };
  • function foo() {} export { foo };
  • class Bar {} export { Bar };

这些导出建立的是静态、只读、实时的绑定:修改 a 的值,所有 import { a } 的地方都会看到新值;但导入方无法给 a 重新赋值(报错 Assignment to const)。

导入方式完全不同,影响可读性和工具链

具名导出必须用对应名称导入:

import { foo, Bar } from './mod.js';

而 default 导出导入时可任意命名:

import greet from './mod.js';
import somethingElse from './mod.js';

这种灵活性带来三个实际问题:

  • 重构困难:改函数名后,所有 default 导入点不会报错,但逻辑失效
  • 类型推导弱:TypeScript 和编辑器难以准确补全 default 导出的内容
  • Tree-shaking 效果差:工具更难判断某个 default 导出是否被真正使用

两者不能混用同一个标识符

模块内可以同时有 default 和具名导出,但不能重复导出同一标识符:

const utils = { log() {} };
export default utils;
export { utils }; // ✅ 合法,导出的是不同绑定

但下面这样会报错:

export const x = 1;
export default x; // ❌ 不允许将已具名导出的 x 再作为 default 导出

因为 default 导出要求是独立的表达式或声明,不是对已有标识符的别名引用。

相关文章

精彩推荐