【问题标题】:How to force the evaluation of a variable inside a for loop in JavaScript?如何在 JavaScript 的 for 循环中强制对变量求值?
【发布时间】:2014-11-11 22:22:38
【问题描述】:

我目前遇到了一个问题,我动态地创建了一组 div,并且在创建它们时,我为它们分配了一个 onclick() 事件。代码的简化版本如下所示:

for(DayOfTheWeek = 0; DayOfTheWeek < 7; DayOfTheWeek++){
  var EventCell = document.createElement('div');
  var EventDayIndex = WeekNumber*7 + DayOfTheWeek + EventoDayOffset;
  EventCell.onclick = function(){ClickableDivFunction(EventDayIndex)};
}

我遇到的问题是我所有的 div 集都使用计算出的最终 EventDayIndex 的参数调用 ClickableDivFunction。这是我所有的 7 个 div 都执行 ClickableDivFunction(6) 而不是我的第一个 div 执行 ClickableDivFunction(0),第二个 ClickableDivFunction(1) 等等。

在此论坛上搜索时,我发现以下answer 解释了我的问题。基本上,EventDayIndex 不会只评估并保留在为 onclick 事件定义的函数中的每次迭代中获得的值。

我尝试了几件事,例如尝试将 EventDayIndex 转换为字符串,希望 ClickableDivFunction 的参数保持其值。尝试添加另一个变量,使用“+”运算符生成一个字符串,然后向 ClickableDivFunction 添加一个过滤器以删除多余的文本(这是我试图通过执行以下操作来强制评估 EventDayIndex:

var NewVar = ClickableDivFunction + "#";

然后删除调用函数中的“#”。)在所有情况下,我得到了相同的结果。 所以我的问题是,你们建议如何以安全、可维护的方式解决这个问题?我假设人们过去会遇到过这个问题,而我只是没有足够的编程知识来知道要搜索什么,但我能想到的解决这个问题的所有方法要么是转换为文本,要么是找到一个按值进行变量赋值的方法。

如果有任何帮助或答案链接,我将不胜感激。

【问题讨论】:

  • 感谢大家的帮助!

标签: javascript


【解决方案1】:

JavaScript 的变量范围是函数,而不是你可能习惯的循环或块。所以,如果你想为每个 div 设置一个单独的变量,你需要一个单独的函数调用。

for(DayOfTheWeek = 0; DayOfTheWeek < 7; DayOfTheWeek++){
  createEventCell(WeekNumber*7 + DayOfTheWeek + EventoDayOffset);
}

function createEventCell(EventDayIndex) {
  var EventCell = document.createElement('div');
  EventCell.onclick = function() { ClickableDivFunction(EventDayIndex); };
}

这是不同的,因为对 createEventCell 的每次调用都有自己的范围(这是您对原始代码中每个循环的预期)。

JavaScript 使得创建新函数并传递它们变得非常容易,因此这最终不会像最初看起来那样繁琐,而且您可能会注意到您的代码变得更小、更紧凑并且重用起来更有趣。当您更熟悉该语言时,请查看 underscore.js。

【讨论】:

    【解决方案2】:

    您看到的“问题”是因为 JavaScript 提升了您的变量。 JavaScript 没有块作用域,它唯一的作用域是函数作用域。这意味着您在函数中声明的所有变量都将绑定到该函数。

    你可以这样写代码:

    function foo() {
      for(DayOfTheWeek = 0; DayOfTheWeek < 7; DayOfTheWeek++){
        var EventCell = document.createElement('div');
        var EventDayIndex = WeekNumber*7 + DayOfTheWeek + EventoDayOffset;
        EventCell.onclick = function(){ClickableDivFunction(EventDayIndex)};
      }
    }
    

    但是 JavaScript 会把它编译成这样:

    function foo() {
      var EventCell, EventDayIndex;
      for(DayOfTheWeek = 0; DayOfTheWeek < 7; DayOfTheWeek++){
        EventCell = document.createElement('div');
        EventDayIndex = WeekNumber*7 + DayOfTheWeek + EventoDayOffset;
        EventCell.onclick = function(){ClickableDivFunction(EventDayIndex)};
      }
    }
    

    现在您可以看到为什么每个函数都会计算相同的值:因为它们使用相同的变量!

    如果要捕获循环的状态,则需要创建另一个范围。正如我之前所说,JavaScript 的唯一作用域是函数作用域,因此您需要创建另一个函数。

    你可以这样做:

    function captureIt(EventDayIndex) {
      return function(){ClickableDivFunction(EventDayIndex)};
    }
    
    function foo() {
      var EventCell, EventDayIndex;
      for(DayOfTheWeek = 0; DayOfTheWeek < 7; DayOfTheWeek++){
        EventCell = document.createElement('div');
        EventDayIndex = WeekNumber*7 + DayOfTheWeek + EventoDayOffset;
        EventCell.onclick = captureIt(EventDayIndex);
      }
    }
    

    或者,您可以使用立即调用的函数表达式 (IIFE):

    function foo() {
      var EventCell, EventDayIndex;
      for(DayOfTheWeek = 0; DayOfTheWeek < 7; DayOfTheWeek++){
        EventCell = document.createElement('div');
        EventDayIndex = WeekNumber*7 + DayOfTheWeek + EventoDayOffset;
        EventCell.onclick = (function(i){
          return function(){ClickableDivFunction(i)};
        }(EventDayIndex));
      }
    }
    

    【讨论】:

      【解决方案3】:

      这应该可以解决问题:

      EventCell.onclick = (function (idx) {
          return function () {
              ClickableDivFunction(idx);
          };
      }(EventDayIndex));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-10-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多