Dreams
Dreams

Reputation: 8506

why we can put a variable in the end of inner function for closure?

var i;
var marker = [];
var infowindow = [];

for(i=0; i<results.length ; i++ ){
    marker[i] = new google.maps.Marker({
        position: results[i].geometry.location,
        map: map
    });

    infowindow[i] = new google.maps.InfoWindow({
        content: "test" + i
    });

    google.maps.event.addListener(marker[i], 'click', function(num) {
        return function() {
            infowindow[num].open(map, marker[num]);
        }
    }(i)); 
}

There is a "(i)" in the end of inner function. Why we can do that? I know that is for closure. But don't know why we can put variable in the end like that? is this a pattern?

Upvotes: 0

Views: 54

Answers (5)

Rod Ferreira
Rod Ferreira

Reputation: 181

First of all, it's important to know that in javascript you can define a function and immediatly call it. Let's see the code below:

function(num){
      alert(num);
}(1234);

If you run this code, you will see an alert dialog with "1234". So we have defined a function that receives a number and shows an alert dialog with it. And then we have called the function immediatly passing "1234" as a parameter.

Knowing that the google maps addListener third parameter must be a function, We can change the return of our function to be another function.

function(num){
     return function(){
            alert(num);
     }
}(1234);

What will happen when you execute the code below? It will return a function that when called shows an alert of "1234". You could store it in another variable to give it a try:

// "test" variable will have the returned function
var test = function(num){
         return function(){
                alert(num);
         }
    }(1234);

test(); // will show the alert with "1234"

Now we can pass it as the event callback

google.maps.event.addListener(marker[i], 'click', test);

And the when you click at the marker an alert will be shown with "1234" as message.

Now back to your code, I know it may be a bit confusing having a function returning another function, but remember that the google maps addListener third parameter must be a function that will be called when the click happens. That's why you have a function returning another function in your example.

And also see that the returned function uses the "num" variable that is defined in its "parent" function. It is in the scope of the function and so it can be used, but what value does this "num" resolve to? That's exactly why you are passing the "i" value. It will make the iterator index (i) to be stored at the "num" variable. So the return function will have access to the correct "i" value.

Now, why you can't use the "i" value directly inside the function? Why you have to store it in another variable (num)? Because It is incremented till the number of markers. So at the end of the loop It will have an static value equal to the length of markers. If you read its value you may endup using the wrong marker.

Upvotes: 0

David Sherret
David Sherret

Reputation: 106640

It's an immediately-invoked function expression (IIFE).

It's done to preserve the value of i at the point in the loop when the IIFE is called. For example, this code...

for (var i = 1; i <= 5; i++) {
    setTimeout(function() {
        console.log(i);
    }, 100);
}

...will output 6, 6, 6, 6, 6.

This is because at the time console.log(i) is called, the value stored in i has already been incremented to 6.

We can fix this by wrapping it in an IIFE to preserve the value of i at the point within the loop.

For example the following code using an IIFE...

for (var i = 1; i <= 5; i++) {
    setTimeout(function(i) {
        return function() {
            console.log(i);
        };
    }(i), 100);
}

...will output: 1, 2, 3, 4, 5.

Upvotes: 0

czheo
czheo

Reputation: 1941

The code below means create an anonymous function and execute it instantly.

(function(num){
  ...
})(i)

Equivalent to

var func = function(num){...}
func(i)

Upvotes: 1

Fallenreaper
Fallenreaper

Reputation: 10682

the (i) at the end of the function is the execution of the function with i as the input parameter. That means that whatever i is, is going to be passed into the function as the arg, num.

Since the function is anon, it isnt able to say func(i) either, so this essentially will define and execute the function all in 1 shot.

Upvotes: 0

Vidul
Vidul

Reputation: 10528

This is an immediate function (also known as self-executing functions), see more here.

Upvotes: 1

Related Questions