词法环境中的块作用域是如何管理的?

How is block scope managed in the lexical environment?

如果我使用 var 在函数中声明一个变量,那么该变量的槽将添加到该函数定义的 LexicalEnvironment 中。

function() {
  var foo; 
}

在上面的代码中,与函数关联的 LexicalEnvironment 包含一个带有键 foo 和值 undefined.

的插槽

如果我使用块作用域声明,周围的 LexicalEnvironment 会受到怎样的影响?

function() {
  {
    let foo; // How does this affect the LexicalEnvironment?
  }
}
function() {
  var foo; 
}

正如您所提到的,fooLexicalEnvironment 中可用,对于该函数内的所有内部函数都是全局的。

但是

function() {
  {
    let foo; // How does this affect the LexicalEnviroinment?
  }
}

此处 foo 仅针对该块。它在那个街区之外是不可见的。

它如何影响 LexicalEnvironment

如果您在该块内的任何位置引用 foo,则局部 let foo 将覆盖您在该函数中定义的全局 var foo

With respect to ES6,

function example(x) {
    console.log(y); // ReferenceError: y is not defined
    if (x) {
        let y = 5;
    }
}

使用 let 语句声明的变量是作为对当前执行上下文的词法环境而非变量环境的绑定创建的。 ES6 中块语句规范的更改意味着每个块都有自己的词法环境。在上面的示例中,在评估块(if 语句的主体)时创建了一个新的词法环境。当 let 语句被评估时,一个绑定被添加到这个词法环境中,并且无法从外部词法环境(函数声明本身的词法环境)访问。

Refer

此类问题最好通过查看 spec:

来回答

Block : { StatementList }

  1. Let oldEnv be the running execution context’s LexicalEnvironment.
  2. Let blockEnv be NewDeclarativeEnvironment(oldEnv).
  3. Perform BlockDeclarationInstantiation(StatementList, blockEnv).
  4. Set the running execution context’s LexicalEnvironment to blockEnv.
  5. Let blockValue be the result of evaluating StatementList.
  6. Set the running execution context’s LexicalEnvironment to oldEnv.
  7. Return blockValue.

NOTE: No matter how control leaves the Block the LexicalEnvironment is always restored to its former state.

那么这里发生了什么?

对块求值时,会创建一个新的词法环境,当前词法环境为"parent"。在评估区块期间,新环境将替换当前环境。

If I use a block-scoped declaration, how is the surrounding LexicalEnvironment affected?

除了临时更换外,完全不受影响