这是一个很常见的 JavaScript/ES module 行为问题。
结论先行:
如果你用
export let foo = ...
方式导出变量,a/b 文件都 import 这个变量,a 文件修改后,b 文件用到的是“被修改后的值”,不是原始值。
详细解释
1. ES Module 的“live binding”特性
- ES6 的模块导出(
export let foo = ...
)和导入(import { foo } from ...
)是活绑定(live binding)。 - 这意味着:import 进来的变量是“引用”,不是“快照”。
2. 举例说明
state.js
export let showPath = false;
export function setShowPath(val) { showPath = val; }
a.js
import { showPath, setShowPath } from './state.js';
setShowPath(true);
console.log('a.js', showPath); // true
b.js
import { showPath } from './state.js';
console.log('b.js', showPath); // 如果 a.js 已经 setShowPath(true),这里就是 true
- 只要 a.js 先执行 setShowPath,b.js 里用到的 showPath 就是 true。
3. 注意事项
export default { showPath }
导出的是一个对象的引用,但对象的属性如果是基本类型(如showPath = true
),则是值的快照,如果是对象/数组,则是地址(引用)。- 如果你用
export const showPath = false;
,则不能被其他模块修改(const 不能重新赋值)。
大坑再强调一遍
- default导出:export default { showPath }
- 基本类型是快照,引用类型是地址。
- 具名导出:export { showPath }
- 无论类型,import 的都是“活的绑定”,原始变量变了,import 的值也会变。