Search code examples
javascriptclosurespass-by-referencelistenerpass-by-value

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


Here is a simplified version of something I'm trying to run:

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

but I'm finding that every listener uses the value of results.length (the value when the for loop terminates). How can I add listeners such that each uses the value of i at the time I add it, rather than the reference to i?


Solution

  • 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.