1

I have an object and i put it in a Array, and the i iterate the array with for and for each object in the array i put a set interval for calling a method of the object with a parameter, but i cant. This is my "Class".

    function ClassTest() {
        this.test = function(word) {
            console.log(word);
        }
    }

The i create the object and put it on a Array:

    var array = [];
    var objectTest = new ClassTest();


    array.push(objectTest);

And when i set the Intervals:

    for(var i = 0; i < array.length; i++) {
        array[i].loop = setInterval(function() {
            array[i].test("hello")
        }, 1000);
    }

The problem is that the var i in the setInterval function dosent exist, i can create a var index and the it exist but i dont understand why index exist and the var i not.:

    for(var i = 0; i < array.length; i++) {
        var index = i;
        array[i].loop = setInterval(function() {
            array[index].test("hello")
        }, 1000);
    }

I get this error when i dont use the index var:

Uncaught TypeError: Cannot read property 'test' of undefined
Raxkin
  • 387
  • 1
  • 3
  • 18
  • By the time you execute the callback of `setInterval`, `i` equals `array.length`. See for example [here](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) how to solve this. – Johannes Egger Apr 02 '15 at 10:24
  • Could you share what's the error coming in first place. Or just "i" doesn't exists. – Prakhar Asthana Apr 02 '15 at 10:24

2 Answers2

2

Because your for loop executes immediately. By the time your setInterval() executes for the first time, your for loop will have long since finished and your i will be outside of the range of your array.

Example

In this example, our array has a length of 3. When our for loop finishes, our i variable will be equal to 3. The number 3 will be displayed three times in our JavaScript console if we log i within the setTimeout:

var array = [1, 2, 3];

for (var i = 0; i < array.length; i++) {
  setTimeout(function() {
    console.log(i);
  }, 1000);
}
James Donnelly
  • 126,410
  • 34
  • 208
  • 218
2

Your attempt is incorrect in both cases, with or without index. There is only one i variable in your code, and by the time the timeouts fire, it will have the value array.length.

This is a problem known as "closing over the loop variable", and one clean way to solve it is:

array.forEach(function (item) {
    item.loop = setInterval(function () {
        item.test("hello");
    }, 1000);
});

This question has several answers that explain in depth the reasons for the behavior you are seeing, but most of the highly-voted answers are excessively convoluted when you're working with an array. forEach is the way to go.

Community
  • 1
  • 1
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • If you need to support IE 8, however, then `Array.prototype.forEach()` is unavailable. – Phylogenesis Apr 02 '15 at 10:30
  • @Phylogenesis If you need to support IE 8, you can use a [polyfill](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach). – JLRishe Apr 02 '15 at 10:31