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

为什么全局声明的let变量无法在new Function中访问而var可以?

问题核心原因

这一差异本质是两个JS语法规则共同作用的结果:

1. new Function的作用域绑定规则

所有通过new Function构造函数创建的函数,不会和创建时的外层作用域形成闭包,它们的执行上下文永远绑定全局作用域。也就是说这类函数运行时,只能访问两类变量:

  • 函数自身内部声明的局部变量
  • 全局作用域下的变量
    无法访问创建new Function时所在的外层局部作用域、模块作用域内的变量。

2. 不同全局声明的存储差异

同样是写在全局脚本最外层的变量,不同声明方式的存储位置不同:

  • 用var声明的全局变量、不写关键字直接赋值生成的隐式全局变量:会自动挂载到**全局对象(浏览器为window,Node.js为globalThis)**上,属于全局作用域可直接访问的变量。
  • 用let、const、class声明的全局变量:不会挂载到全局对象上,而是存储在全局作用域的词法环境记录中,本身仍然属于全局变量,正常情况下可以被全局作用域下运行的代码访问。

触发报错的常见场景

如果你确实把let value写在普通非模块脚本的最外层,new Function是可以正常访问到的,你遇到报错的最可能原因是运行代码的环境不是全局作用域:

场景1:代码运行在ES模块中

如果你的代码是放在<script type="module">标签里,或是Node.js的ES模块文件中,那么文件最外层的作用域不是全局作用域,是模块私有作用域:

  • 你在顶层写的let value = "test"只是模块内部的私有变量,不属于全局变量
  • new Function创建的函数绑定全局作用域,自然找不到只存在于模块作用域的value
    如果你测试时var可以正常输出,大概率是测试var时用了普通非模块脚本,测试let时切换到了模块环境。

场景2:let value实际声明在局部作用域中

如果你是把let value = "test"写在了某个回调函数(比如window.onload、DOM事件回调)、自定义函数的内部,那么它只是该函数的局部变量,不属于全局变量,new Function自然无法访问。
而如果你此时用value = "test"不写关键字赋值,会自动生成隐式全局变量,挂载到全局对象上,所以new Function可以访问到。

验证&解决方案

你可以加一行打印确认value的作用域归属:

let value = "test";
console.log(window.value); // 普通全局脚本输出undefined,模块/局部作用域输出undefined,var声明的全局变量输出'test'
function getFunc() {
    let func = new Function('console.log(value)');
    return func;
}
getFunc()();

如果要在模块/局部作用域下让new Function可以访问到value,可以手动把它挂载到全局对象上:

let value = "test";
window.value = value; // 手动挂载到全局对象
function getFunc() {
    let func = new Function('console.log(value)');
    return func;
}
getFunc()(); // 正常输出test

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 04:54:03