【问题标题】:How does this unexpected output comes?这个意想不到的输出是怎么来的?
【发布时间】:2019-02-01 16:19:37
【问题描述】:

console.log(i);
    for(var i=0;i<2;i++){
          console.log(i);
    }

这在浏览器中显示了一些意外的输出。谁能解释一下? 输出是:

它在不同的控制台上实际上是完全不同的。 Mozilla 文档是这样说的:

// myVarVariable 在这里可见

for (var myVarVariable = 0; myVarVariable // myVarVariable 对整个函数可见 }

// myVarVariable 在这里可见

【问题讨论】:

  • “意外”部分到底是什么?
  • 问题是什么?它的行为似乎与我预期的完全一样——你得到undefined,然后是0,然后是1应该发生什么?
  • JavaScript loop variable scope 的可能重复项 - 嗯。这实际上可能已经过时了。 let 似乎反驳了这个答案,但对于 OP 正在使用的当前实现,它是正确的。
  • @RaghavMaheshwari ifor 循环之前可用赋值 不是。文档是正确的 - 它涵盖了 变量 的可见性,而不是分配。
  • 我得到undefined10。我从这里复制粘贴了你的整个 sn-p 作为运行的单个代码。

标签: javascript


【解决方案1】:

这是由于吊装。在 javascript 中,使用 var 声明的变量显示提升。提升是一个过程,其中所有变量的声明都被带到 java 脚本范围的顶部。但请注意,它们没有被分配下面代码中分配的值。 letconst 不显示此行为

console.log(x);
var x = 4;
console.log(y)
let y = 4

【讨论】:

    【解决方案2】:

    您的代码中没有任何 unexpected,它的行为应如此。

    console.log(i);
    

    由于 javascript 中称为 hoisting 的概念,此日志语句打印 undefined。当您使用 var 关键字定义变量时,它们会在 javascript 运行时被移动/提升到函数/本地范围的顶部。

    现在你可能会问,如果变量声明被移动/提升到函数/局部范围的顶部,那么为什么记录 i 会打印 undefined?那是因为只有变量声明被提升到顶部,而不是变量的值。因此,当您在循环之前记录i 时,它会为您提供undefined,因为Javascript 识别出变量i 存在于此范围内,但尚未赋予值。

    for loop 内部,变量i 被初始化为值0,然后循环执行两次并为您提供01

    现在您还可以在for loop 之后访问变量i,这是因为var功能范围。这意味着使用关键字var 定义的变量如果未在任何函数中定义,则全局可用。

    如果您不希望出现这种行为,请使用 let 而不是 varlet 关键字提供块级范围,这意味着使用let 关键字定义的变量仅在定义它们的块中(大括号之间)可用。

    【讨论】:

    • 谢谢你们!现在一切都清楚了。对我来说是一个非常愚蠢的困惑。
    【解决方案3】:

    将变量声明为let,这不会发生。还要检查this

    【讨论】:

    • 没关系,但代码与Mozilla网站上的官方文档不同步。
    • @RaghavMaheshwari 怎么不同步?行为与您引用的文档一致 - 第一个 console.log(i) 有效,因为 i 在那里可见,文档也说。
    • @RaghavMaheshwari Mozilla 不拥有任何“官方”文档,因为它们不是标准的所有者。 Ecma International 拥有 EcmaScript/JavaScript 标准,而 W3C 拥有其他 Web 标准。虽然在这种情况下并非如此,但他们完全有可能在其网站上提供不正确的信息。
    • @DavidCrane 即使您将代码块复制/粘贴到控制台中(而不是逐行粘贴),您也会得到提升。它不仅在功能范围内。此外,它在全局范围内工作,这就是为什么我们可以使用很多东西,这要归功于提升函数声明。
    • @skyline3000 有问题的网站是 MDN - Mozilla 开发者网络。它实际上不是 Mozilla 的财产,它是一个公共 wiki。那里的信息被认为是非常高质量的,并且与官方文档一样被接受。不 - 这种情况下的信息没有错 - OP中引用的部分非常准确。这是误解它的意思。 OP 似乎希望将var i = 0 的行i 设置为零,并且您会在到达该行之前看到该值。文档从未声称是这种情况。
    【解决方案4】:

    由于variable hoistingvar 声明被物理移动到其执行上下文范围的顶部(在本例中为全局范围)。因此,您的代码与以下内容相同:

    var i;
    console.log(i);
    for(i=0;i<2;i++){
        console.log(i);
    }

    【讨论】:

      【解决方案5】:

      在 javascript 内部循环中使用 ler 代替 var... 然后您甚至可以为变量使用相同的名称并获得不同的结果。下面的例子:

      var x = 1;
        if (true) {
          var x = 2;  // same variable
          console.log(x);  // 2
         }
         console.log(x);  // 2
         }
      
          function letTest() {
          let x = 1;
          if (true) {
            let x = 2;  // different variable
            console.log(x);  // 2
          }
          console.log(x);  // 1
         }
      

      【讨论】:

        猜你喜欢
        • 2018-10-14
        • 1970-01-01
        • 2019-04-11
        • 2018-11-06
        • 2020-11-09
        • 2011-12-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多