Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I pass the value (not the reference) of a JS variable to a function? [duplicate]

People also ask

How do I pass a value from one function to another in JavaScript?

When there are multiple functions (which is most of the time), there needs to be a way to pass data between the functions. This is done by passing values in parenthesis: myFunction(myData). Even when there is no data to be passed, we still have to declare and execute functions by using parenthesis: myFunction().

Is JS pass by reference or value?

JavaScript is always pass-by-value. This means everything in JavaScript is a value type and function arguments are always passed by value. That being said, object types are a bit more confusing. The confusion lies in the fact that object types are reference types which are passed by value.

Does JS pass function parameters by value or by reference?

In JavaScript, all function arguments are always passed by value. It means that JavaScript copies the values of the variables into the function arguments. Any changes that you make to the arguments inside the function do not reflect the passing variables outside of the function.


In modern browsers, you can use the let or const keywords to create a block-scoped variable:

for (let i = 0; i < results.length; i++) {
  let marker = results[i];
  google.maps.event.addListener(marker, 'click', () => change_selection(i));
}

In older browsers, you need to create a separate scope that saves the variable in its current state by passing it as a function parameter:

for (var i = 0; i < results.length; i++) {
  (function (i) {
    marker = results[i];
    google.maps.event.addListener(marker, 'click', function() { 
      change_selection(i);
    }); 
  })(i);
}

By creating an anonymous function and calling it with the variable as the first argument, you're passing-by-value to the function and creating a closure.


As well as the closures, you can use function.bind:

google.maps.event.addListener(marker, 'click', change_selection.bind(null, i));

passes the value of i in as an argument to the function when called. (null is for binding this, which you don't need in this case.)

function.bind was introduced by the Prototype framework and has been standardised in ECMAScript Fifth Edition. Until browsers all support it natively, you can add your own function.bind support using closures:

if (!('bind' in Function.prototype)) {
    Function.prototype.bind= function(owner) {
        var that= this;
        var args= Array.prototype.slice.call(arguments, 1);
        return function() {
            return that.apply(owner,
                args.length===0? arguments : arguments.length===0? args :
                args.concat(Array.prototype.slice.call(arguments, 0))
            );
        };
    };
}

closures:

for (var i = 0, l= results.length; i < l; i++) {
    marker = results[i];
    (function(index){
        google.maps.event.addListener(marker, 'click', function() { 
            change_selection(index);
        }); 
    })(i);
}

EDIT, 2013: These are now commonly referred to as an IIFE


You're winding up with a closure. Here's an article on closures and how to work with them. Check out Example 5 on the page; that's the scenario you're dealing with.

EDIT: Four years later, that link is dead. The root of the issue above is that the for loop forms closures (specifically on marker = results[i]). As marker is passed into addEventListener, you see the side effect of the closure: the shared "environment" is updated with each iteration of the loop, before it's finally "saved" via the closure after the final iteration. MDN explains this very well.