[英]Illegal Shadowing (Shadowing let with var)
考虑以下 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
在全局 scope 中声明, let a
在块 scope 中。 但是为什么这在第一种情况下无效? 在那里, let a
将在单独的 scope 中声明,而var a
应在全局 scope 中声明。 为什么这个案子无效?
但是为什么这在第一种情况下无效?
因为这两个声明都在同一个 scope中。¹您的第二个示例有效,因为let
仅适用于块,而不是存在var a
的块之外的 scope 。 (就像 function 中的局部变量一样。)所以在第二个示例中,它是阴影。 在第一个示例中,它不会是阴影,而是重复,这是您无法使用let
做的(即使其他声明使用var
)。 (您可以使用var
在同一个 scope 中多次声明一个变量。随后的var
被忽略,尽管变量上的任何初始化程序都被转换为赋值。例如, var a; var a = 42;
与var a; a = 42;
相同var a; a = 42;
)
¹ 好的,从技术上讲,它比这要复杂一些。 var
变量存在于“外部”全局词法环境中,该环境在全局 object 上保存绑定(松散地,变量),但let
变量存在于“内部”全局词法环境中,该环境不保持其在全局 object 上的绑定。 全局 scope 仍然只是一个 scope,所以正如你所见,你不能在全局 scope 上同时拥有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"
由于内部更接近执行console.log(a)
的代码,因此上述输出"answer"
。
有趣的事实:根据您的计算方式,在浏览器上,“全局”环境有两到六层。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.