【问题标题】:let Variable Scope让变量范围
【发布时间】:2017-05-11 06:40:32
【问题描述】:

以下代码将输出“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();

【问题讨论】:

  • 我认为这是因为das 在定义x 的块内.. 就在两个块内,但其中一个也围绕let 所以没关系跨度>
  • x 不必是 global 以便在嵌套函数中可见;它只需要在本地范围或某个外部范围内即可。 let 声明不仅将可见性限制在本地范围内;它是本地范围加上任何嵌套范围。
  • 换句话说,嵌套函数内的代码包含let的块的一部分。
  • 也许我错了,但我认为这与吊装无关。

标签: javascript variables let


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 所以“让”限制了外部范围,而不是内部范围?
  • @GTSJoe 我刚刚评论了另一个答案。没有“内部范围”之类的东西。
  • @GTSJoe 换句话说,嵌套函数体的{ } 与作用域中出现的for 循环的{ } 没有什么不同。
  • @GTSJoe 也看到我的更新;我意识到我对 let 的工作方式遗漏了一些细微差别。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    问题是您没有改变 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 的值,编译器会报错。

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

        【解决方案5】:

        @GTS 乔,

        let xletTest() 上下文的本地变量,因此das() 只是访问它的x 变量。那里没有什么奇怪的事情发生。所以,“不”——它没有成为全球性的。

        无论变量调用的上下文嵌套多深,总有一个查找JS原理,这将在失败的 环顾 之后继续查找该变量名,直到整个全局范围内,然后 - 当什么都没有时找到 - 这将导致引用错误。

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

        【讨论】:

          【解决方案6】:

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

          一个很好的例子是在下面的 switch 案例中,在案例 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);
          

          【讨论】:

            【解决方案7】:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2020-08-10
              • 2014-01-31
              • 2011-02-10
              • 2020-02-07
              • 2012-12-23
              相关资源
              最近更新 更多