【问题标题】:Block scope variables in 'For' and 'For-of' loops'For' 和 'For-of' 循环中的块范围变量
【发布时间】:2018-04-25 11:50:13
【问题描述】:
// Prints
// Meow!
// I'm a talking cat!
// Callbacks are fun!

function go() {
   const messages = ["Meow!", "I'm a talking cat!", "Callbacks are fun!"];
   let msg = [];
   for (let i = 0; i < messages.length; i++) {
      msg.push(function () {
          print(messages[i]);
      });
   }
   for (let fct of msg ) {
      fct();
   }
}
go();

// Prints
// Callbacks are fun!
// Callbacks are fun!
// Callbacks are fun!

function go() {
   const messages = ["Meow!", "I'm a talking cat!", "Callbacks are fun!"];
   let msg = [];
   for (let message of messages) {
      msg.push(function () {
          print(message);
      });
   }
   for (let fct of msg ) {
      fct();
   }
}
go();

我了解到 let 使变量具有块作用域并解决了使用 var 声明变量的缺点。即 let 允许每次迭代为变量捕获不同的值。正如我上面的第一个示例所示,这适用于传统的 for 循环。然而,令我惊讶的是,如果我在 ES6 中使用 for..of 循环结构,函数闭包中的每次迭代都不会捕获变量“消息”!这是为什么呢?

【问题讨论】:

  • 您确定此代码将第三条消息打印三次吗?它对我有用。
  • 后者对我来说也能按预期工作。尽管console.log() 可能是比print() 更好的调试选择:)
  • 我很高兴你们得到了预期的结果。但是,是的,我得到了字符串“回调很有趣!”打印 3 次。嗯..现在我很困惑为什么我得到的结果与你们不同。我应该说我在 Ubuntu604 上,并安装了带有 JavaScript-C24.2.0 版本的 Spidermonkey JS shell。不确定这是否会有所不同。

标签: javascript for-loop let


【解决方案1】:

原来我的 JS shell 已经过时了。当迁移到最新的 SpiderMonkey 45 时,它按预期工作。

【讨论】:

    【解决方案2】:

    我认为问题在于您如何使用 .push() 方法。 试试下面的代码,它将使用任一语法正确地控制台记录您的数组。

    在这种情况下, var 和 let 都会有相同的结果。 您声明的所有变量将仅在它们声明的函数内具有作用域。

    function go() {
     const messages = ["Meow!", "I'm a talking cat!", "Callbacks are fun!"];
     let msg = [];
     for (let i = 0; i < messages.length; i++) {
        msg.push(messages[i]);
        };
    
     for (let fct of msg ) {
        console.log('for',fct);
     };
    };
    go();
    
    function go2() {
     const messages = ["Meow!", "I'm a talking cat!", "Callbacks are fun!"];
     let msg = [];
     for (let message of messages) {
        msg.push(message);
     };
     for (let fct of msg ) {
        console.log('for-of', fct);
     };
    };
    
    go2();
    

    【讨论】:

    • 感谢@Gerard 对此进行了尝试,但您的建议与我所要求的根本不同,那就是它看起来像是函数闭包中的变量捕获声明的变量不起作用。但它确实适用于最新的 Spidermonkey JS。
    • 将函数推送到数组并没有错。推送消息本身而不是打印它们的函数是不一样的。
    猜你喜欢
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 2011-05-27
    相关资源
    最近更新 更多