Christopher Francisco
Christopher Francisco

Reputation: 16278

Maintain reference inside a for-loop Javascript

I have the following code:

for(var i = 0; i < nodelist.length; i++) {
    var x = functionThatCreatesADivElement();

    someElement.appendChild(x.getDiv());  // this works fine

    nodelist[i].onclick = function() {
       x.someFunction();                  // this always refer to the last 'x' object
    }
}


function functionThatCreatesADivElement() {
   var div = document.createElement("div");

   this.someFunction = function() {}

   this.getDiv = function() {
      return div;
   }

   return this;
} 

the problem is that the execution of nodelist[0].onclick is exactly the same as nodelist[4].onclick (assuming that i = 4 is the last node).

I believe the references of the previously iterated are changing to point to the currently iterated element.

What is the proper way of doing this?

EDIT: Added some more code and changed the name of the function cause it was too confusing

Upvotes: 0

Views: 69

Answers (2)

andrezsanchez
andrezsanchez

Reputation: 363

You have two problems. The first problem is that JavaScript variables don't have block scopes.

From MDN:

When you declare a variable outside of any function, it is called a global variable, because it is available to any other code in the current document. When you declare a variable within a function, it is called a local variable, because it is available only within that function.

JavaScript does not have block statement scope;

You aren't enclosing a the x variable in a function, so all of your onclick callbacks are using the same x variable, which point to whatever element is last in the loop since that will be the last one to have overwritten x.

Doing this for your loop should work:

nodelist.forEach(function (nodeitem) {
    var x = functionThatCreatesADivElement();

    someElement.appendChild(x.getDiv());

    nodeitem.onclick = function() {
        x.someFunction();
    }
});

The second problem is that your functionThatCreatesADivElement() constructor function is not being called correctly. Use new functionThatCreatesADivElement() since you are invoking a constructor function.

Upvotes: 1

Christopher Francisco
Christopher Francisco

Reputation: 16278

Solved. I had to use

var x = new functionThatCreatesADivElement();

function functionThatCreatesADivElement() {
   var div = document.createElement("div");

   this.someFunction = function() {}

   this.getDiv = function() {
      return div;
   }

   //return this;  //Using new instead of returning this

}

Upvotes: 0

Related Questions