1

How can I get this

var i = 0;
var codes = [1, 2, 3];

for (var i = 0; i < codes.length; ++i)
{
    setTimeout(function(){alert(codes[i]);},100);
}

To alert 1, 2 and 3 without using let keyword?

or bind an event on an element (example):

var i = 0;
var codes = [1, 2, 3];

for (var i = 0; i < codes.length; ++i)
{
    $("div").eq(i).click(function(){
        alert( codes[i] );
    });
}
Kara
  • 6,115
  • 16
  • 50
  • 57
BrunoLM
  • 97,872
  • 84
  • 296
  • 452

5 Answers5

4

Use a self-executing anonymous function and pass in i as an argument for variable closure.

var i = 0;
var codes = [1, 2, 3];

for (var i = 0; i < codes.length; ++i)
{
    (function( index ) {
        setTimeout(function(){alert(codes[index]);},100);
    })(i);
}

Here's an example.

mVChr
  • 49,587
  • 11
  • 107
  • 104
3

You need to make use of a closure. I typically create a "generator" function that returns a function which is defined in the desired context:

var i = 0;
var codes = [1, 2, 3];
function callbackGenerator(i) { 
   return function(){alert(codes[i]);}
}

for (var i = 0; i < codes.length; ++i)
{
    setTimeout(callbackGenerator(i), 100);
}

More info and good examples here: https://developer.mozilla.org/en/JavaScript/Guide/Closures

peepsalot
  • 422
  • 4
  • 7
1
var i = 0;
var codes = [1, 2, 3];

var timeoutFunc = function() {
    alert(codes[i++]);
    if (i < codes.length) {
        setTimeout(timeoutFunc, 100);
    }
};

setTimeout(timeoutFunc, 100);
Orbling
  • 20,413
  • 3
  • 53
  • 64
1

This should do it.

var codes = [1, 2, 3];

for (var i = 0; i < codes.length; ++i)
    setTimeout(function(code){return function(){
        alert(code);
    }}(codes[i]), 100);
jairajs89
  • 4,495
  • 3
  • 18
  • 14
1

Use a self-executing function:

for (var i = 0; i < codes.length; ++i) (function(bound_i) {
    setTimeout(function(){alert(codes[bound_i]);},100);
})(i);

Optionally using a var statement for more verbose code:

for (var i = 0; i < codes.length; ++i) (function() {
    var bound_i = i;
    setTimeout(function(){alert(codes[bound_i]);},100);
})();

Or use a named function instead if you want to:

function foo(i) {
    setTimeout(function(){alert(codes[i]);},100);
}

for (var i = 0; i < codes.length; ++i) {
    foo(i);
}

Either example forms a closure, which introduces new variable scope. Alternatively, ES5 has Function.bind that could be used on the anonymous function, but it is not universally supported in all browsers yet. (I'm thinking of IE.)

Community
  • 1
  • 1
PleaseStand
  • 31,641
  • 6
  • 68
  • 95