首页 > 解决方案 > 托管 let, const

问题描述

/* Hoisting exampe - let */
let a = 100;
{
	console.log(a); // 100
}
{
	console.log(a); // ReferenceError: a is not defined
	let a = 50;
}

/* Hoisting took place in {}. */
{
	let a=100;
	console.log(a); // 100
}
console.log(a); // ReferenceError: a is not defined

首先,我知道这一点let并且const有一个块范围
编译发生在执行上下文单元中,提升发生在LexicalEnvironment创建时。
执行上下文是由global , function , eval代码的执行创建的。

不应该在global , function , eval代码单元中提升const和完成吗? (似乎提升似乎没有发生,但这完全归功于 TDZ 的帮助。内部 const 和 let 提升。)let

如果引擎在创建执行上下文时遇到块{/* code */}(而不是函数),引擎是否会为块添加新范围?[[Scope]]

标签: javascriptexecutioncontext

解决方案


第一次遇到块时(使用),会创建{一个新的执行上下文,这会创建一个新的空词法环境(它基本上是一个容器,将当前直接作用域中的变量名映射到它们的值)。然后引擎遍历所有用立即块声明或在立即块中初始化的变量。(但是,尽管已初始化,但在引擎真正遇到or线 - TDZ 之前,它们是不可引用的)constletconst <variableName>let <variableName>

因此,普通块确实创建了一个新范围,如果该块内的任何语句使用constor声明变量,则该范围将被填充let

您可以使用调试器看到这一点:

/* Hoisting took place in {}. */
{
    debugger;
    let a=100;
    console.log(a); // 100
}
console.log(a); // ReferenceError: a is not defined

Chrome devtools 中的结果:

在此处输入图像描述

(虽然,这有点误导 -a实际上并不包含undefined,它当时还没有完全创建)

和变量名称被提升constlet因为解释器从块的开头识别出引用它们是非法的,直到它们通过constorlet行完全创建。

它不仅仅是简单的块 -任何级别的代码都会导致发生相同类型的事情(例如在顶层,或在for块内,或在函数内)。


推荐阅读