前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库ESM 重复导出同名变量报错
JavaScript模块与语言机制

一个模块里导出两个同名的变量会怎样?和默认导出能重名吗?

不能。一个模块的导出名必须唯一,重复了会在解析阶段报 SyntaxError: Duplicate export,整个模块一行都不执行。但同一个变量可以用多个名字导出,默认导出本质上就是一个叫 default 的导出名,所以和具名导出不冲突,只是不能有两个 default。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#模块与语言机制
先看核心答案读代码示例
理解线索

导出名的唯一性规则

  1. 导出名模块对外暴露的名字,一个模块里不能重复
  2. 本地变量名模块内部的变量,可以用多个导出名暴露出去
  3. default一个特殊的导出名,重复写两次默认导出同样报错

export * 是例外:两个被转发的模块有同名导出时不报错,这个名字直接从导出里消失。直到有人具名导入它,才会报错。

核心回答

先记住这个答案

不能。ESM 要求一个模块里的导出名唯一,不管是两次 export const a,还是 export { a } 写了两遍,都会报 SyntaxError。这个检查发生在解析阶段,所以模块里任何代码都不会执行,导入它的模块也跟着加载失败。要分清两个概念:导出名必须唯一,但同一个本地变量可以用多个不同的导出名暴露出去。

  • 导出名重复在解析阶段就报 SyntaxError
  • 同一个变量可以用多个名字导出
  • 默认导出就是名叫 default 的导出,只能有一个
  • export * 名字冲突不报错,而是两个都丢掉

哪些写法会报错

下面每一组都是一个独立的模块文件,报错信息来自 Node.js。

三种常见的重复导出JavaScript
// 1. 声明时就重名:本地变量都重复了
export let x = 1
export function x() {} // SyntaxError: Identifier 'x' has already been declared

// 2. 导出列表写了两遍
const y = 1
export { y }
export { y } // SyntaxError: Duplicate export of 'y'

// 3. 两个默认导出
const z = 1
export { z as default }
export default 2 // SyntaxError: Duplicate export of 'default'

第一种其实是本地变量重复声明,let 不允许同一作用域重名,和导出无关。第二、三种才是导出名重复。第三种说明 export default 和 export { z as default } 是一回事,都在注册一个名叫 default 的导出。

哪些写法看起来重名但没问题

同一个变量可以导出多次,只要导出名不同。比如 export { format, format as formatDate },外面用哪个名字导入都行,两个名字指向同一个变量。库在重命名 API 时常这样做,旧名字保留一段时间兼容老代码。

默认导出和具名导出也可以指向同一个东西。export default format 加上 export { format },导出名一个是 default、一个是 format,不冲突。很多库同时提供两种导入方式就是这么写的。

重新导出时的冲突

export { a } from './x.js' 这种显式转发,和本模块自己的 a 撞了一样会报 SyntaxError。

export * 比较特殊。index.js 里写了 export * from './a.js' 和 export * from './b.js',两个模块都导出了 version,这时不会报错,version 会被悄悄排除,两个都不导出。有人 import { version } from './index.js' 才报 SyntaxError: The requested module contains conflicting star exports for name 'version',而用 import * as ns 拿到的命名空间对象上根本没有 version。如果 index.js 自己显式导出了 version,那就以显式导出为准,不存在冲突。

回答前,多想一步

容易答错的地方

以为后一个导出会覆盖前一个
有些人按对象属性的思路想,觉得后写的覆盖先写的。模块导出不是对象赋值,是静态声明,重复就是语法错误,没有覆盖这回事。
以为默认导出和同名具名导出会冲突
export default function format() {} 和 export { format } 能共存吗?能。默认导出的导出名是 default,不是 format。函数名 format 只是本地变量名。
以为报错时模块已经执行了一部分
语法错误在解析阶段就发现了,模块代码一行都不执行,依赖它的整个模块图也不会执行。不会出现执行了一半的中间状态。
试着用自己的话回答

面试官还会怎么问?

TypeScript 能在编码时就发现吗?

能。TypeScript 编译器会报重复标识符或重复导出的错误,编辑器里直接标红。打包工具在解析阶段也会报错,所以这类问题一般到不了线上。

桶文件里 export * 冲突了怎么排查?

冲突的名字会悄悄消失,症状是某个导出「明明有却导入不到」。可以用 import * as ns 打印 Object.keys(ns) 看少了哪个,再逐个检查被转发的模块。修法是在桶文件里用 export { version } from './a.js' 显式指定要哪一个。

CommonJS 里重复给 exports.a 赋值会报错吗?

不会。exports 就是一个普通对象,后赋的值覆盖先赋的,没有任何提示。这也是 ESM 静态导出的好处之一,重名问题在解析阶段就暴露了。

从一道题,走向一组知识

把知识连起来

模块与语言机制

动态 import() 返回的是什么?为什么它是异步的?

模块有语法错误时,动态 import() 返回的 Promise 会拒绝,可以在 catch 里捕获到这个 SyntaxError。

模块与语言机制

动态 import() 里能用变量或模板字符串当路径吗?

和本题关系不大,讲的是动态 import() 的路径能不能用变量拼接。

参考资料

  • JavaScript:模块与语言机制参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 哪些写法会报错
  3. 哪些写法看起来重名但没问题
  4. 重新导出时的冲突
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑