ES6模块中导出冲突为何会被静默移除?
为什么重导出同名变量时JavaScript会忽略冲突的导出?
先看你给出的代码示例:
// a.mjs export * from "./b.mjs"; export * from "./c.mjs"; // b.mjs export const foo = 1; export const bar = 2; // c.mjs export const bar = 3;
这种情况的核心原因是ES模块规范对export *的冲突处理规则:当你通过export *从多个模块批量重导出时,如果多个源模块存在同名的导出标识符,这个同名标识符会被直接排除在当前模块的导出列表之外——既不会触发报错,也不会发生覆盖。
为什么是这种设计?
export *是批量导入导出的语法,规范制定者认为这种场景下的同名冲突是“间接的”:你没有明确指定要保留哪一个模块的bar,引擎无法确定你的真实意图。如果随便覆盖,可能违背你的预期;如果直接报错,又容易因为这种间接冲突中断程序。于是选择了最保守的处理方式:忽略这个冲突的导出。
如何控制同名导出的优先级?
如果想要明确指定保留某一个模块的bar,需要用明确的重导出语法替代export *中的同名项,比如:
// a.mjs export * from "./b.mjs"; export { bar } from "./c.mjs"; // 明确指定导出c.mjs的bar
此时a.mjs会导出foo(来自b.mjs)和bar(来自c.mjs),因为明确的重导出优先级高于export *的批量处理。
反过来,如果是直接重复明确导出同名标识符,引擎才会报错——因为这属于开发者明确的错误操作,比如:
// a.mjs export { bar } from "./b.mjs"; export { bar } from "./c.mjs"; // 解析阶段会触发语法错误
总结
export *批量重导出遇到同名时,会静默排除该同名导出- 明确重复导出同名标识符时,会触发语法错误
- 明确的重导出会覆盖
export *中的同名项
内容的提问来源于stack exchange,提问作者AFatNiBBa
相关产品推荐
相关产品推荐

