最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How to force the evaluation of a variable inside a for loop in JavaScript? - Stack Overflow

programmeradmin0浏览0评论

I'm currently running into a problem where I dynamically create a set of divs and, while creating them, I assign an onclick() event to them. A simplified version of the code looks like this:

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

The problem I have is that all my set of divs call ClickableDivFunction using the argument of the final EventDayIndex calculated. This is All my 7 divs execute ClickableDivFunction(6) instead of my first div executing ClickableDivFunction(0), the second ClickableDivFunction(1) and so on.

While searching on this forum I found the following answer which explains my problem. Basically EventDayIndex will not just evaluate and leave the value it got on every iteration in the function defined for the onclick event.

I tried several things such as trying to cast EventDayIndex into a string hoping the argument of ClickableDivFunction would keep its value. Trying to add another variable, generating a string using '+' operator and then adding a filter to ClickableDivFunction to remove the extra text (This is I was trying to force the evaluation of EventDayIndex by doing:

var NewVar = ClickableDivFunction + "#";

and then removing the "#" in the calling function.) In all cases I got the same result. So my question is, how would you guys remend to solve this problem in a safe, maintainable way? I'd assume people would have encountered this problem in the past and I just don't have enough knowledge in programming to know what to search for but all the things I could think to solve this problems were either, casting to text or finding a way to make an variable assignment by value.

I'd appreciate any help on this or a link to the answer.

I'm currently running into a problem where I dynamically create a set of divs and, while creating them, I assign an onclick() event to them. A simplified version of the code looks like this:

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

The problem I have is that all my set of divs call ClickableDivFunction using the argument of the final EventDayIndex calculated. This is All my 7 divs execute ClickableDivFunction(6) instead of my first div executing ClickableDivFunction(0), the second ClickableDivFunction(1) and so on.

While searching on this forum I found the following answer which explains my problem. Basically EventDayIndex will not just evaluate and leave the value it got on every iteration in the function defined for the onclick event.

I tried several things such as trying to cast EventDayIndex into a string hoping the argument of ClickableDivFunction would keep its value. Trying to add another variable, generating a string using '+' operator and then adding a filter to ClickableDivFunction to remove the extra text (This is I was trying to force the evaluation of EventDayIndex by doing:

var NewVar = ClickableDivFunction + "#";

and then removing the "#" in the calling function.) In all cases I got the same result. So my question is, how would you guys remend to solve this problem in a safe, maintainable way? I'd assume people would have encountered this problem in the past and I just don't have enough knowledge in programming to know what to search for but all the things I could think to solve this problems were either, casting to text or finding a way to make an variable assignment by value.

I'd appreciate any help on this or a link to the answer.

Share Improve this question edited May 23, 2017 at 12:27 CommunityBot 11 silver badge asked Nov 9, 2014 at 19:46 ThelemitianThelemitian 3551 silver badge15 bronze badges 1
  • Thanks everybody for your help! – Thelemitian Commented Nov 21, 2014 at 22:23
Add a ment  | 

3 Answers 3

Reset to default 4

JavaScript scopes its variables by function, not by loop or block as you might be used to. So, if you want a separate variable for each of your divs, you need a separate function call.

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

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

This is different because each call to createEventCell gets its own scope (which is what you expected to happen for each loop in your original code).

JavaScript makes it pretty easy to make new functions and pass them around, so this ends up not being as cumbersome as it seems at first, and you may notice that your code gets smaller, tighter, and more fun to reuse. When you're more familiar with the language, check out underscore.js .

The "problem" you are seeing is because of JavaScript hoisting your variables. JavaScript does not have block scope, the only scope it has is function scope. This means all the variables you declare inside a function, will be bound to the function.

You may write code like this:

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

But JavaScript will pile it to this:

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)};
  }
}

Now you can see why every function will evaluate the same value: because they use the same variable!

If you want to capture the state of the loop, you need to create another scope. As I said earlier, the only scope JavaScript has is the function scope, so you need to create another function.

You can do it this way:

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);
  }
}

Or, you can use an immediately invoked function expression (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));
  }
}

This should do the trick:

EventCell.onclick = (function (idx) {
    return function () {
        ClickableDivFunction(idx);
    };
}(EventDayIndex));
发布评论

评论列表(0)

  1. 暂无评论