javascript - JavaScript 的词法环境如何在嵌套的 block 范围内维护变量声明?

标签 javascript callstack hoisting lexical-scope lexical

我已经阅读了几篇关于执行上下文的更全面的文章,现在我有点困惑和困惑。
为了使问题尽可能简短,避免冗长的引用,我最好尝试通过一个专注于我无法获得的细节的例子来说明我的心理模型,以便您可以纠正我并指出错误。
这是一个例子:

var tomato = 'global tomato';

{
  let tomato = 'block tomato';
  console.log(tomato); // 'block tomato'
}

console.log(tomato); // 'global tomato'
到目前为止,一切都清楚了。当 JS 引擎创建一个执行上下文时(在我们的例子中是全局的)var tomato第一行的声明被放入 Variable Environmentlet tomato在 block 范围内进入 Lexical Environment .这就解释了我们是如何得到两种不同的西红柿的。
现在,让我们添加另一个番茄,如下所示:
var tomato = 'global tomato';

{
  let tomato = 'block tomato';

  {
    console.log(tomato); // ReferenceError: Cannot access 'tomato' before initialization
    let tomato = 'nested block tomato';
  }

  console.log(tomato); // won't reach here
}

console.log(tomato); // won't reach here
ReferenceError不足为奇。事实上,我们试图在变量被初始化之前访问它,这被称为时间死区。这很好地表明 JS 已经创建了 另一个变量 tomato在最嵌套的 block 内。 JS 也意识到了这一点 tomato在我们引用它的那一刻未初始化。否则,它会抓取 tomato从等于 'block tomato' 的外部范围没有抛出任何错误。所以让我们修复错误并交换行,如下所示:
var tomato = 'global tomato';

{
  let tomato = 'block tomato';

  {
    let tomato = 'nested block tomato';
    console.log(tomato); // 'nested block tomato'
  }

  console.log(tomato); // 'block tomato' - still 'block tomato'. Nothing has been overwritten.
}

console.log(tomato); // 'global tomato'
我想知道的是 JavaScript 如何管理这个最嵌套的 block 。因为当执行到达该行时:

let tomato = 'nested block tomato';

Lexical Environment的执行上下文已经包含变量 tomato它在外部范围内初始化,值为 'block tomato' .假设 JS 没有为代码块创建新的执行上下文(分别使用 Lexical 和 Variable 环境)(这只是函数调用和全局脚本的情况,对吧?),显然,它不会覆盖现有的变量Lexical Environment具有相同名称但来自嵌套 block 范围的那些。正如最后一段代码所示,创建了一个全新的自变量来保存值 'nested block tomato' .
那么问题是这个变量究竟存储在哪里?我的意思是只有一个 Lexical Environment对于执行上下文,但我们可能会创建许多嵌套范围,在其中声明变量。我正在努力想象这些变量将存储在哪里以及整个事情如何组合在一起。

最佳答案

Assuming JS doesn't create a new execution context (with Lexical and Variable environments respectively) just for the blocks of code (that's only the case for function invocations and global script, right?)


这是一个错误的假设。
the specification :

A Lexical Environment is a specification type used to define the association of Identifiers to specific variables and functions based upon the lexical nesting structure of ECMAScript code. A Lexical Environment consists of an Environment Record and a possibly null reference to an outer Lexical Environment. Usually a Lexical Environment is associated with some specific syntactic structure of ECMAScript code such as a FunctionDeclaration, a BlockStatement, or a Catch clause of a TryStatement and a new Lexical Environment is created each time such code is evaluated.


block 语句创建了一个新的词法环境。

关于javascript - JavaScript 的词法环境如何在嵌套的 block 范围内维护变量声明?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64512611/

相关文章:

java - 获取 Java 堆栈跟踪中涉及的对象

assembly - 我可以从堆栈的中间弹出吗?

JavaScript 提升

javascript - 如何使用 nodejs 发送 udp 包?

javascript - 当执行这个特定的 onclick 事件时如何执行 JavaScript 函数?

javascript - 如何更改过滤器中的 servletRequest 内容长度

javascript - 如何从下拉列表中获取所选文本的第一个字符并将其放入文本框中?

计算堆栈上的帧数

javascript - 提升是针对完整代码立即进行还是按嵌套函数级别进行

Javascript 变量和函数提升