gavenkoa
gavenkoa

Reputation: 48753

Passing by value instead by reference to JavaScript closure - any non-wrapping technique?

Variables passed to closure by reference. This code:

var figs = ['circle', 'square'];
for (var i in figs) {
    var fig = figs[i];
    document.getElementById(fig).addEventListener("click", function(e) {
        console.log(fig);
    }, false);
}

always log last array element even you click to circle (square, last value of fig variable).

In order to bind actual value of fig variable I use wrapping in function call (so intermediate closure hold loop value):

var figs = ['circle', 'square'];
for (var i in figs) {
    var fig = figs[i];
    document.getElementById(fig).addEventListener("click", (function(fig) {
        return function(e) {
            console.log(fig);
        }
    })(fig), false);
}

Is that possible to avoid wrapping-function in order to pass by value?

UPDATE related questions and answers:

Upvotes: 1

Views: 448

Answers (2)

plalx
plalx

Reputation: 43718

You can also use bind and pass an object that encapsulates the variables you need. Then you can make use of this.fig inside the handler to reference your figure.

document.getElementById(fig).addEventListener("click", (function(e) {
     console.log(this.fig);
}).bind({ fig: fig }), false);

You can also bind a primitive value directly, however it will be wrapped in it's respective object wrapper e.g. Number for a number, String for a string, etc.

document.getElementById(fig).addEventListener("click", (function(e) {
    //this will be the same as new String(fig)
}).bind(fig), false);

Upvotes: 2

lonesomeday
lonesomeday

Reputation: 237865

No, it is not possible.

However, you can make your code a bit nicer, by taking the code that produces the inner function out of the loop:

var figs = ['circle', 'square'];
function createFigHandler(fig) {
    return function(e) {
        console.log(fig);
    }
}

for (var i = 0; i < figs.length; i++) {
    var fig = figs[i];
    document.getElementById(fig).addEventListener("click", createFigHandler(fig), false);
}

jsFiddle

Upvotes: 4

Related Questions