首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JavaScript的词法环境如何维护嵌套块作用域中的变量声明?

JavaScript的词法环境如何维护嵌套块作用域中的变量声明?
EN

Stack Overflow用户
提问于 2020-10-24 10:58:05
回答 2查看 468关注 0票数 6

我读过几篇关于执行上下文的更全面的文章,现在我有点困惑和困惑。

为了使问题尽可能简短,避免长时间引用,我最好尝试通过一个集中在我无法获得的细节上的例子来说明我的心智模型,这样你就可以纠正我并指出错误。

下面是一个示例:

代码语言:javascript
复制
var tomato = 'global tomato';

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

console.log(tomato); // 'global tomato'

到目前为止,一切都很清楚。当JS引擎创建执行上下文(在本例中为全局上下文)时,第一行的var tomato声明被放置到Variable Environment中,而块范围内的let tomato则被放入Lexical Environment。这就解释了为什么我们最后得到了两个不同的西红柿。

现在,让我们再加一个番茄,就像下面这样:

代码语言:javascript
复制
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。而且,JS在我们引用这个tomato的时候就已经意识到它没有初始化。否则,它就会从等于'block tomato'的外部范围抓取'block tomato',而不会抛出任何错误。因此,让我们修复错误并交换行,如下所示:

代码语言:javascript
复制
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如何管理这个最嵌套的块。因为当执行到达行时:

let tomato = 'nested block tomato';

执行上下文的Lexical Environment已经包含变量tomato,该变量在外部作用域中以'block tomato'值初始化。假设JS不为代码块创建一个新的执行上下文(分别使用了词汇环境和变量环境)(这只是函数调用和全局脚本的情况,对吗?)显然,它不会用同名但来自嵌套块作用域的变量覆盖现有Lexical Environment中的变量。如最后一段代码所示,其中创建了一个全新的独立变量来保存值'nested block tomato'

那么问题是这个变量究竟存储在哪里?我的意思是,执行上下文只有一个Lexical Environment,但是我们可以创建一个嵌套的作用域,在其中声明变量。我很难想象这些变量将被存储在哪里,以及这些变量是如何整合在一起的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-10-24 11:09:40

假设JS不为代码块创建一个新的执行上下文(分别使用了词汇环境和变量环境)(这只是函数调用和全局脚本的情况,对吗?)

这是一个错误的假设。

请参阅规格

词汇环境是一种规范类型,用于根据ECMAScript代码的词法嵌套结构定义标识符与特定变量和函数的关联。词汇环境由一个环境记录和一个可能为空引用的外部词汇环境组成。通常,词汇环境与ECMAScript代码的某些特定的句法结构相关联,例如FunctionDeclaration、BlockStatement或TryStatement的Catch子句,每次计算这些代码时都会创建一个新的词汇环境。

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

票数 5
EN

Stack Overflow用户

发布于 2020-10-24 11:10:17

在ECMAScript中,词法作用域可以嵌套。

我的意思是,执行上下文只有一个词汇环境,但是我们可能会创建一个嵌套的作用域,在其中声明变量。

不,…有一个词汇环境well…每个词汇环境。(“范围”毕竟是“环境”的另一个术语。)

规范并不强制实现者以任何特定的方式实现这一点。一种典型的方法可能是有链接的环境列表。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64512611

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档