不建议在模块化环境下用 globalthis 建立“原始状态共享后门”,因其缺乏作用域隔离、生命周期管理与并发保护,易致竞态、跨上下文不互通及打包不可控;应改用 es 模块单例、显式 context 传递、di 容器或 har/hsp 封装等受控方式。

不建议在模块化环境下用 globalThis 建立“原始状态共享后门”。这不是设计初衷,也违背现代 JavaScript 模块化原则。
为什么 globalThis 不该被当作状态共享后门
globalThis 是一个**只应承载环境无关的全局基础设施**(如 polyfill 注入、跨平台工具函数、底层运行时钩子)的只读锚点,不是状态容器。它没有作用域隔离、无生命周期管理、无并发保护,且在多上下文环境(如 ArkTS 多 context、Web Worker、Node.js ESM/CJS 混合)中行为不可控:
- 多个模块同时写
globalThis.myState,会相互覆盖,尤其在并发请求或动态加载场景下极易引发竞态 - ESM 环境中无法访问
global,但误以为globalThis可自由挂载变量,实际可能因模块缓存机制导致状态不一致 - HarmonyOS ArkTS 中,每个
napi_create_ark_context创建的上下文拥有独立的globalThis,跨 context 写入不互通,形成“伪共享” - 打包工具(如 Rollup/Webpack)对
globalThis上的属性无法做 tree-shaking 或依赖分析,增加体积且隐藏耦合
真正受控的跨模块状态共享方式
模块化系统中,状态共享必须有明确所有权、可见范围和更新契约。推荐以下替代路径:
-
ES 模块单例导出:在独立文件中定义并导出一个状态管理实例(如
state.ts),所有模块仅 import 它——天然单例、可类型推导、支持热更新 -
显式 context 参数传递:将状态对象作为
context参数注入到函数或类构造器中,避免隐式依赖,便于测试与追踪 - 依赖注入容器:使用轻量 DI 方案(如手动构造器注入或 awilix),按需绑定生命周期(如 request-scoped 状态),确保销毁可控
- HAR/HSP 封装状态服务:在 HarmonyOS 中,将状态逻辑封装为 HAR 包(静态复用)或 HSP 包(动态加载),通过接口契约暴露方法,而非暴露裸对象
极少数允许碰 globalThis 的边界场景
仅限底层适配层,且必须满足:只读、幂等、无副作用、带命名空间隔离:
- 注入 polyfill:
if (!globalThis.AbortController) { globalThis.AbortController = MyPolyfill; } - 注册跨环境调试钩子:
globalThis.__DEVTOOLS__ = { dumpState: () => ({ ... }) };(仅开发环境启用) - 在 Node-API C++ 层为每个
napi_env初始化专属globalThis属性(如globalThis.__nodeApiEnvId),用于运行时上下文识别
把状态逻辑塞进 globalThis,就像把钥匙焊死在门框上——看似方便,实则锁不住安全,也关不上维护成本。










