【问题标题】:Using const as loop variable in for loop在 for 循环中使用 const 作为循环变量
【发布时间】:2019-09-27 06:09:28
【问题描述】:

我了解在typescript/javascript 中使用varfor 循环中的varlet 的行为,但有人可以解释为什么以及如何将const 变量作为循环变量的行为?

for (const i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log(i)
  }, 100 * i);
}

据我了解,当您将变量声明为const 并初始化其值时,该值无法更改

但是您可以看到 console.log() 中的值正在更改。编译时必须抛出错误吗?我在这里缺少什么?

我为此行为创建了 2 个示例。

Loop variable as a const

Const variable re assignment

有人可以帮助我理解这一点吗?

【问题讨论】:

  • constlet 都具有块作用域,并在其定义的块的顶部提升,constlet 之间的唯一区别是声明的变量 const 不能重新初始化
  • 请在问题本身中包含所有代码,而不仅仅是在外部网站上。
  • @messerbill 一个真正的 ES2015 环境确实有常量。
  • @HereticMonkey 我会包含代码,但如果不是堆栈闪电战示例,我将无法显示该行为。我希望你明白我的意思
  • 如果是这样,并且您知道该行为只能在 Stackblitz 中复制,那么您应该在问题中提及这一点。

标签: javascript angular typescript ecmascript-6


【解决方案1】:

它可以在 Stackblitz 中运行,因为它运行的是经过转换的代码:

AppComponent.prototype.test = function () {
    var _loop_1 = function (i) {
        setTimeout(function () {
            console.log(i);
        }, 100 * i);
    };
    for (var i = 0; i < 5; i++) {
        _loop_1(i);
    }
};

如果你在这里添加一个 sn-p 它将不起作用,因为它没有被转译

for (const i = 0; i < 5; i++) {
  setTimeout(function() {
    console.log(i)
  }, 100 * i);
}

【讨论】:

  • 看起来我不应该太信任 stackblitz 或者我不明白 stackblitz 是如何工作的。非常感谢您消除疑虑。所以我假设循环会中断是正确的。
  • @CruelEngine tbf,它确实在i++ 下显示红色波浪线,并带有错误消息:“无法分配给'i',因为它是一个常量或只读属性。"
  • 但它编译了,这就是我有点困惑的地方
【解决方案2】:

回答您的问题,

  test(){
    for(const i =0 ; i< 5; i++){
      setTimeout(function(){
        console.log(i)
      },100*i);
    }
  }

这段代码基本上变成了,

  test(){

    // can be only initialized once
    const i;
    for(i = 0 ; i< 5; i++){
      setTimeout(function(){
        console.log(i)
      },100*i);
    }
  }

因为每个 JavaScript 变量在其作用域的顶部都是 hoisted,在这种情况下,test() 作为它的 const 变量,这就是为什么它在该块中被提升并且在它之外无法访问的原因。

更正这段代码:

  test(){

    // can be only multiple times in that block
    for(let i = 0 ; i< 5; i++){
      setTimeout(function(){
        console.log(i)
      },100*i);
    }
  }

变成这样,

  test(){

    let i;
    // can be only multiple times in that block
    for(i = 0 ; i< 5; i++){
      setTimeout(function(){
        console.log(i)
      },100*i);
    }
  }

由于constlet 都具有block scope 并在其定义的块的顶部提升,constlet 之间的唯一区别是声明为 const 的变量不能重新初始化。

【讨论】:

  • 吊装与这种行为无关吧?如果我声明 const 的循环变量,则循环永远不会运行
  • @CruelEngine 你不能在初始化后增加const 变量
  • 是的,但代码在我在问题中附加的示例中运行
  • @CruelEngine 我认为 webpack 正在将代码转换为 ES3 以保持兼容性,而 constlet 没有,const 被转换为 var。无论如何,您可以检查 dist 文件夹中的转译文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-12
  • 2019-12-19
  • 2020-04-05
  • 2021-04-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多