问题描述
考虑以下 JavaScript 中的阴影示例:
let a = 99;
{
var a = 10;
let b = 11;
const c = 200;
console.log(a);
}
console.log(a);
这里出现以下错误:
SyntaxError: Identifier 'a' has already been declared
var a = 99;
{
let a = 10;
let b = 11;
const c = 200;
console.log(a);
}
console.log(a);
在第二种情况下,var a
在全局范围内声明,而 let a
在块范围内声明。
但是为什么这在第一种情况下无效?
在那里,let a
将在单独的范围内声明,而 var a
应在全局范围内声明。
为什么这个案例无效?
解决方法
但是为什么这在第一种情况下无效?
因为这两个声明都在相同的范围中。¹您的第二个示例有效,因为 _MyAppState
的范围仅限于块,而不是块外的范围,其中 {{ 1}} 存在。 (就像函数中的局部变量。)所以在第二个例子中,它是阴影。在第一个示例中,它不会是阴影,而是重复,而您无法使用 let
(即使另一个声明使用 var a
)。 (您可以在同一范围内使用 let
多次声明一个变量。随后的 var
被忽略,尽管该变量的任何初始化器都被转换为赋值. 例如,var
等同于 var
)
¹ 好的,从技术上讲,它比那要复杂一些。 var a; var a = 42;
变量存在于“外部”全局词法环境中,该环境包含全局对象上的绑定(松散地,变量),但存在 var a; a = 42;
变量在“内部”全局词法环境中,该环境不将其绑定在全局对象上。全局作用域仍然只是一个作用域,因此正如您所见,您不能将 var
和 let
都放在全局作用域中,因为它们彼此冲突。但是还有其他方法可以创建“外部”全局变量,例如分配给 var a
(或全局范围内的 let a
,或现代环境中的 window
)上的属性:
this
这意味着可以在外部和内部全局词法环境中创建绑定:
globalThis
由于内部更接近执行 // At global scope
window.a = 42; // Creates binding in the outer global environment
console.log(a); // Shows 42
的代码,因此上述输出 // At global scope
window.a = 42; // Creates binding in the outer global environment
let a = "answer"; // Creates binding in the inner global environment
console.log(a); // Shows "answer"
。
有趣的事实:根据您的计算方式,在浏览器上,“全局环境”有两到六层层。?