user1553136
user1553136

Reputation: 328

Javascript : Pass String by value

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

Answers (3)

Alnitak
Alnitak

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

Shreedhar
Shreedhar

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

jbabey
jbabey

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

Related Questions