如何以类似window[name]的方式动态访问const和let声明?
为什么
const/let声明的变量没法像var那样通过window访问? 这个问题其实是ES6变量声明机制和旧版JS的核心差异之一,我来给你掰扯清楚:
- 旧版JS里,用
var在全局作用域声明变量时,会自动把这个变量挂载到浏览器的全局对象window上,所以你能通过window['x']或者window.x轻松拿到它。 - 但ES6引入的
const和let就不一样了——它们在全局作用域声明时,不会被挂载到window对象上。这些变量会被存在一个独立的「全局环境记录」里,和window的属性完全是两个分离的体系,所以你用window['y']自然拿不到值,只会返回undefined。
那如果我必须通过字符串名称访问const/let声明的变量,该怎么办?给你几个可行的方案:
方案1:手动把变量挂载到window(简单但不推荐)
如果是你自己声明的变量,可以主动把它添加到window对象上,这样就能用window[变量名]访问了:
const y = 7; let z = 21; // 两种写法都可以 window.y = y; window['z'] = z; console.log('y = ' + window['y']); // 输出:y = 7 console.log('z = ' + window['z']); // 输出:z = 21
不过这种方式会污染全局对象,大型项目里尽量少用,避免变量冲突。
方案2:用自定义容器管理变量(推荐)
更好的做法是自己创建一个全局对象来存放需要动态访问的变量,这样既不会污染window,又能灵活通过字符串访问:
// 自定义一个全局变量容器 const globalStore = {}; const y = 7; let z = 21; // 把变量存到容器里 globalStore.y = y; globalStore['z'] = z; // 通过字符串名称访问 console.log('y = ' + globalStore['y']); // 输出:y = 7 console.log('z = ' + globalStore['z']); // 输出:z = 21
这种方式更可控,也符合现代JS的模块化思想,推荐优先用这个。
方案3:用eval()(极端情况才用,强烈不推荐)
实在没辙的时候,可以用eval()来执行字符串形式的变量名,但这个方法有很大的安全风险——如果传入的字符串是用户输入的,很容易引发代码注入攻击,而且eval会影响代码性能,所以除非万不得已,别碰它:
const y = 7; let z = 21; console.log('y = ' + eval('y')); // 输出:y = 7 console.log('z = ' + eval('z')); // 输出:z = 21
额外补充
- 在Node.js环境里,全局作用域的
var会挂载到global对象,但const/let同样不会;现在可以用globalThis来统一访问所有环境的全局对象(浏览器和Node都支持),但还是改变不了const/let不挂载到全局对象的特性。 - 如果是在ES模块(比如用
import/export的文件)里,哪怕是var也不会挂载到window,因为模块有自己独立的作用域。
内容的提问来源于stack exchange,提问作者Pilaf T. Pilafian
相关产品推荐
相关产品推荐

