export default 是具名导出的特殊别名,本质是导出名为 default 的单一绑定,每模块仅限一个,不参与命名空间枚举,且原始值导出无动态绑定。

JavaScript 中的 export default 并不是一种独立的导出机制,而是对“默认导出”这一语义的语法糖——它的本质是为模块指定一个**可被匿名导入的主值**,背后仍依赖于模块系统的单例绑定与动态绑定规则。
默认导出的本质:一个具名导出的特殊别名
export default 在底层等价于一次具名导出,其导出名称固定为 default。例如:
export default function foo() {}
等价于:
function foo() {}
export { foo as default };
这意味着:模块内部只有一个 default 绑定,它和其它具名导出(如 export const a = 1)共存于同一导出对象中,但 default 是唯一允许在导入时不写大括号的成员。
核心限制一:每个模块仅允许一个 default 导出
语法层面禁止重复声明,默认导出只能出现一次(无论是否在同一文件中多次写 export default)。这是因为模块的 [[Exports]] 内部记录中,default 键是唯一的,重复赋值会触发语法错误。
立即学习“Java免费学习笔记(深入)”;
- ✅ 允许:
export default class A{}或export default function(){}或export default 42 - ❌ 不允许:
export default 1; export default 2;(SyntaxError) - ⚠️ 注意:表达式必须有明确值,不能是单纯的函数声明(需加括号或赋值给变量),否则会因提升行为导致意外结果
核心限制二:default 导出不参与命名空间对象的展开
使用 import * as ns from './mod' 时,ns.default 存在,但 default 不会自动混入命名空间对象的枚举属性中(即 Object.keys(ns) 不包含 'default'),这是 ES 模块规范的明确设计——default 是一个特殊访问通道,而非普通导出成员。
因此,以下写法无法解构到 default 值:
import * as mod from './mod';
const { default: x } = mod; // ❌ 运行时报错:default is not exported
正确方式仍是:import x from './mod' 或 import { default as x } from './mod'。
核心限制三:动态绑定不适用于 default 导出的直接赋值形式
当用表达式直接导出(如 export default 1 + 1),该值在模块求值时被计算并固化,后续对原始变量的修改不会反映到 default 导出上;而若导出的是变量引用(如 let x = 1; export default x;),则实际导出的是初始值的拷贝,不是响应式绑定。
- ✅ 动态绑定生效的情况:导出一个对象或函数,再修改其属性或内部状态
- ❌ 动态绑定失效的情况:导出原始值、或导出后重新赋值变量本身(如
x = 2不会影响已导出的default)
理解 export default 的本质,关键在于看清它只是模块系统为简化常用场景提供的便捷入口,而非绕过模块绑定规则的“特权”。它轻便,但有边界;它灵活,但不模糊语义。










