在JavaScript中能否创建不可变的globalThis全局变量?
实现只读全局变量的几种方法
要让globalThis上的变量实现类似const/readonly的只读效果,有两种可靠方案,既能跨模块直接访问,又能阻止意外修改:
1. 使用Object.defineProperty定义只读属性
这是最直接的方案,通过对象属性描述符限制读写与配置权限:
'use strict'; // 定义只读全局变量 Object.defineProperty(globalThis, 'APP_CONFIG', { value: { apiUrl: 'https://example.com/api', timeout: 5000 }, writable: false, // 禁止修改属性值 configurable: false, // 禁止删除或重新配置该属性 enumerable: true // 可选,允许通过for...in或Object.keys枚举 }); // 尝试修改会抛出错误(严格模式下) APP_CONFIG.apiUrl = 'new-url'; // Uncaught TypeError: Cannot assign to read-only property 'apiUrl' of object '#<Object>' // 尝试删除也会失败 delete APP_CONFIG; // Uncaught TypeError: Cannot delete property 'APP_CONFIG' of #<Object>
如果变量是引用类型(对象、数组),writable: false仅能阻止替换整个引用,无法限制内部属性修改。若需深度只读,可配合Object.freeze():
const frozenConfig = Object.freeze({ apiUrl: 'https://example.com/api' }); Object.defineProperty(globalThis, 'APP_CONFIG', { value: frozenConfig, writable: false, configurable: false });
2. 使用Proxy实现带拦截提示的只读变量
如果需要更灵活的控制(比如拦截修改时给出自定义错误提示),可以用Proxy包装全局对象:
'use strict'; // 先初始化变量值 globalThis.APP_CONFIG = Object.freeze({ apiUrl: 'https://example.com/api' }); // 创建全局代理,拦截指定属性的修改 const protectedGlobal = new Proxy(globalThis, { set(target, prop, value) { if (prop === 'APP_CONFIG') { throw new Error(`错误:全局变量 ${prop} 是只读的,无法修改`); } target[prop] = value; return true; }, deleteProperty(target, prop) { if (prop === 'APP_CONFIG') { throw new Error(`错误:全局变量 ${prop} 无法删除`); } delete target[prop]; return true; } }); // 后续通过代理访问全局(模块环境中可将代理导出共享) protectedGlobal.APP_CONFIG = 'new value'; // Uncaught Error: 错误:全局变量 APP_CONFIG 是只读的,无法修改
关键注意事项
- 必须开启严格模式:非严格模式下修改只读属性会静默失败,难以排查问题,建议所有代码开头加上
'use strict';。 - 跨模块可用性:在ES模块或CommonJS中,
globalThis定义的变量可直接在任何模块访问,无需导入。 - 避免命名冲突:全局变量容易和第三方库命名冲突,建议使用项目专属前缀(比如
MYAPP_XXX)。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

