Reputation: 10946
I am binding a function to an html element.
there is some data in loop which is changing on each iteration
data = {
networkId: networkId,
network_avatar: network_avatar,
network_user_name: network_user_name,
}
Here I am binding it:
$("#element"+i).bind(function(){
change(data);
}
The function is:
function change(data){
console.log(data);
}
There should be the different data in data
variable on each iteration.
But the it always contains the content of last iteration.
Why jQuery changes the data that is already binded with change()
function
Upvotes: 0
Views: 117
Reputation: 94499
Try nesting the function within another function to create a closure. The trick with a closure is that you must have two nested functions, an inner function and an outer function. The inner function will possess a copy of the outer functions variables & parameters, in a sense inheriting its scope. In my example bindClick serves as the outer function, while the anonymous function within the call to $.click() serves as the inner function. This results in the anonymous inner function retaining the data object passed into the bindClick() method as a parameter. When we run this in a loop we essentially end up with 10 closures that remember the data object they were created with.
Live Example: http://jsfiddle.net/cDwEk/1/
function bindClick(data){
$("#element" + data.myProp).click(function(){
//anonymous function will remember state of outer functions variables.
alert(data.myProp);
});
}
//ForLoop
for(var i = 0; i < 10; i++){
var data = {myProp:i};
//Pass function to another function to create closure.
bindClick(data);
}
Upvotes: 1
Reputation: 1942
First of all, don't use global variables named "data" or "window" or anything else like this. If the declaration of your variable data is somewhere in vision area use "var" bareword.
When the event handler is called, it calls the "change" function and sending the current value of data in it. What you need, is to declare own data for each handler. And you should use "var" for it. Like:
$("#element"+i).bind(function(){
var currentDataValue = new CopyData(data);
change(currentDataValue);
}
function CopyData(object) {
var data = {};
for (var val in object)
data[val] = object[val];
return data;
}
I guess it should help. But i'm not too sure.
Upvotes: 1