You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何通过import * as导入模块后可修改const导出值?

为什么修改ES模块对象的属性会改变原const导出的值,且Chrome控制台显示有差异?

这是个非常典型的ES模块绑定特性问题,咱们一步步拆解来搞明白:

一、为什么修改constants.APPLE会影响导入的APPLE?

ES模块的导出机制和CommonJS完全不同,核心在于它是绑定关系,而非值拷贝:

  • 当你在constants.js里写export const APPLE = 'apple'时,这个APPLE导出的不是一个固定的值,而是一个和模块内部变量绑定的引用。
  • 用import { APPLE } from './constants.js'导入时,你拿到的APPLE并不是导入时刻的快照,而是和模块内部原变量实时联动的绑定。
  • 而import * as constants得到的模块对象,它的所有属性都是这些绑定的“代理入口”。当你执行constants.APPLE = 'banana'时,本质是通过模块系统的底层机制修改了原模块中绑定的变量值——这里绕开了const的声明限制,因为你不是直接在原模块里重新赋值const APPLE,而是通过模块对象的属性操作修改了绑定的实际值。

直接修改APPLE = 'banana'会报错,是因为这个变量在当前模块的作用域里是const声明的,语法层面不允许重新赋值;但通过模块对象修改的是绑定的底层值,不属于当前作用域的const限制范畴。

二、为什么Chrome控制台的显示会有差异?

Chrome DevTools对模块对象的处理有个特殊的惰性求值机制:

  • 当你console.log(constants)时,控制台会先打印一个对象的“快照字符串”,这个字符串是当时对象的表层状态。
  • 但模块对象的属性是动态绑定的,当你点击展开这个对象查看APPLE属性时,控制台会实时重新读取绑定的当前值,这就导致展开后的属性值和初始打印的表层字符串不一致。
  • 简单说就是:初始打印的是“静态快照”,展开时才会获取“动态实时值”,所以看起来和console.log(APPLE)的直接输出有差异。

最后提醒

这种修改模块绑定值的操作属于非常规手段,严重违背了ES模块设计中“导出变量应保持不可变性”的初衷,会导致代码的可维护性急剧下降——所有导入这个变量的模块都会被意外影响,排查问题时会非常头疼,强烈不推荐使用!

内容的提问来源于stack exchange,提问作者Sumire

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:22:03