让变量作用域

let Variable Scope

以下代码将输出“1”。但是,关键字 "let" 不应该使 x 成为全局变量,从而使其对 das() 不可见吗? let 应该将变量的范围限制为仅声明它们的块,但在这里,我看到内部函数可以访问 "let" 变量,即使 x 声明在其范围之外。这怎么可能?

function letTest() {
 function das () {
  console.log(x);
// How does this function have access to a let variable declared outside its scope?
 }

 let x = 1;
 das();
}
letTest();

let 将变量的范围限制在当前块(在这种情况下与 letTest 函数相同)。

das 函数在该范围内声明,因此它可以访问该范围内的任何内容(包括 x)。

下面是 let 工作原理的思考方式:

  1. let.
  2. 开始
  3. 在相同的嵌套级别,back/up 通过源代码,找到第一个 {
  4. 现在从let中找到对应的}.

这为您提供了变量可见的范围。如果函数定义出现在该范围内,那很好;该变量对该函数中的代码可见。

现在,little 有点奇怪的是,在您的示例中,变量 看起来像 它用于范围 之前它被宣布。这就是引用出现在声明之前这一事实变得更有趣的地方。

通常,如果作用域中的代码在 let 实际发生之前引用 let 声明的变量,那就是错误。但是,这是运行时的事情,而不是语法的事情。在您的情况下,在运行时 let 将在调用嵌套函数时具有 "happened"。

问题是你没有改变 x 的值,在你的情况下你只是将它记录到控制台并且它们都嵌套在一个不限制内部函数的范围内,所以你的结果是预期的.

现在如果你做了这样的事情

function letTest() {
    function das () {
        console.log(x);
// How does this function have access to a let variable declared outside its scope?
    }
    let x = 1;
    function change(){
       x = x + 1;
    }

    change();
}
letTest();

现在您试图更改 x 的值,编译器会报错。

如此处所述:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let 它提供块范围内的访问。由于您的 das() 执行和 x 声明在同一块范围内,因此它将具有访问权限。

下面的 switch case 就是一个很好的例子,在 case 1 中使用 var x = 'x' 会导致它附加到函数作用域并且可以在 console.log() 中访问,但是当尝试引用用于记录它的 bar 变量会引发引用异常。但在默认情况下仍然有效。

const example = (foo) => {
    switch(foo) {
        case 0:
            break;
        case 1:
            let bar = 'bar';
            var x = 'x';
            break;
        default:
            console.log(bar);
            break;
    }

    console.log(x);
    console.log(bar);
}

example(1);

该函数在与 x 相同的块中声明,因此函数内的代码可以访问 x

如果您不想这样,您可以随时添加新块:

function letTest() {
  function das () {
    console.log(x); // ReferenceError
  }
  { // New block
    let x = 1;
    das();
  }
}
letTest();

@GTS 乔,

let xletTest() 上下文的局部变量,因此 das() 只是访问它的 x 变量。那里没有什么奇怪的事情发生。所以,'no' - 它没有成为全球性的。

无论变量调用的context嵌套多深,总有一个查找JS原理,失败后环顾四周会继续在全局范围内一直查找这个变量名,只有在没有找到时才会导致引用错误。

那 - 只是因为没有 看下面 JS 原则 - 所谓的 闭包 是可能的。

不在范围内。 xdas() 定义在同一块作用域中。该块中的任何其他内容都可以访问 x。这包括任何嵌套函数、for 循环、while 循环和 if 条件。这包括 elseifelse,它们位于 if 条件句中。