Reputation: 328
I have a little problem with one of my javascript code. Here is the code
//assume array is an array containing strings and myDiv, some div in my doc
for(var i in array) {
var myString = array[i];
var a = document.createElement('a');
a.innerHTML = myString;
a.addEventListener("click", function() {myFunc(myString)}, false);
myDiv.appendChild(a)
}
function myFunc(s) {alert(s);}
However, since Strings are passed by reference in JavaScript, I see always the last string of my array
when I click on the link a
in question. Thus, my question is "How can I pass myString
by value ?". Thank you for your help !
Phil
Upvotes: 3
Views: 4085
Reputation: 339786
Primitive variables are not passed by reference in Javascript.
This is the classic 'loop variable called inside a closure' problem.
Here's one commonly-used solution to that problem:
for (var i = 0, n = array.length; i < n; ++i) {
var myString = array[i];
var a = document.createElement('a');
a.innerHTML = myString;
a.addEventListener("click", make_callback(myString), false);
myDiv.appendChild(a)
}
function make_callback(s) {
return function() {
alert(s);
}
}
Note that this isn't particularly memory efficient since it creates a new function scope for every element in the array.
A better solution might be to store the variable data actually on the element (i.e. as a new property) and retrieve that in the callback. In fact you're already storing that string in the .innerHTML
property so you could just read that and then take advantage of delegation to register just the one handler on the elements' parent:
for (var i = 0, n = array.length; i < n; ++i) {
var a = document.createElement('a');
a.innerHTML = array[i];
myDiv.appendChild(a)
}
myDiv.addEventListener('click', function(ev) {
alert(ev.target.innerHTML);
}, false);
Upvotes: 2
Reputation: 5640
try this : i think its always good not practice to iterate array using for...in
for(var i=0; i<array.length;i++) {
var myString = array[i];
var a = document.createElement('a');
a.innerHTML = myString;
a.addEventListener("click", function() {myFunc(myString)}, false);
myDiv.appendChild(a)
}
function myFunc(s) {alert(s);}
Upvotes: -1
Reputation: 46647
You should add a closure around your event handler:
JavaScript closure inside loops – simple practical example
a.addEventListener("click", function (s) {
return function () {
alert(s)
};
}(myString), false);
Also, you should not use for...in
loops on arrays.
Upvotes: 2