jskidd3
jskidd3

Reputation: 4783

Multiple different event listeners in for loop

The code below always returns undefined. Why is this? I want the event listener to respond with the string of the index.

Thanks

var array = ["Hey", "Hi", "Hello"];

for (var i = 0; i < array.length; i++) {
  var box = document.createElement("div");
  box.className = "box";
  box.addEventListener("click", function() {
    alert(array[i]);
  }, false);
}

Upvotes: 0

Views: 161

Answers (3)

Scott Sauyet
Scott Sauyet

Reputation: 50797

Possibly the simplest solution would be this:

box.addEventListener("click", alert.bind(window, array[i]), false);

But this won't work in IE<9.

Upvotes: 0

user2437417
user2437417

Reputation:

This is asked frequently. JavaScript doesn't have block scope. Variable scope is only created when you invoke a function. So to scope your i to the current loop iteration, you need to reference it in a function invocation that also creates the handler.

// Create a function that returns a function
function createHandler(i) {
    // The value of `i` is local to this variable scope

    // Return your handler function, which accesses the scoped `i` variable
    return function() {
        alert(array[i]);
    }
}

var array = ["Hey", "Hi", "Hello"];

for (var i = 0; i < array.length; i++) {
  var box = document.createElement("div");
  box.className = "box";

  // Invoke the `createHandler`, and pass it the value that needs to be scoped.
  // The returned function will use its reference to the scoped `i` value.
  box.addEventListener("click", createHandler(i), false);
}

I would strongly encourage you to use named functions for this instead of the trendy inline function invocations. It's potentially more efficient, and the function name provides documentation as to the purpose of the function.

Upvotes: 2

McGarnagle
McGarnagle

Reputation: 102753

You need to wrap the click handler in a closure, to create a local copy of i:

box.addEventListener("click", (function(i) { 
  return function() {
    alert(array[i]);
  }
})(i), false);

Fiddle

The way your code is now, i ends up with a value of 3, and array[3] is of course undefined. The above creates 3 copies of i with values 0, 1, 2.

Upvotes: 1

Related Questions