为什么我们可以在内部函数的末尾放一个变量来进行闭包?

时间:2015-07-31 18:29:29

标签: javascript

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)); 
}

有一个&#34;(i)&#34;在内在功能的最后。 为什么我们能做到这一点?我知道这是关闭的。 但是不知道为什么我们最终可以把变量放到那个?这是一种模式吗?

5 个答案:

答案 0 :(得分:1)

这是一个立即函数(也称为自执行函数),请参阅更多here

答案 1 :(得分:1)

下面的代码意味着创建一个匿名函数并立即执行它。

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

相当于

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

答案 2 :(得分:0)

函数末尾的(i)是执行带有i作为输入参数的函数。这意味着无论i是什么,它都将作为arg num传递给函数。

由于函数是anon,它也不能说func(i),所以这基本上将定义并执行1个镜头中的所有函数。

答案 3 :(得分:0)

它是immediately-invoked function expression(IIFE)。

在调用IIFE时,保留i在循环点的值已完成。例如,这段代码......

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

...将输出6, 6, 6, 6, 6

这是因为在调用console.log(i)时,i中存储的值已经增加到6

我们可以通过将其包装在IIFE中来修复此问题,以保留循环内点i的值。

例如以下代码使用IIFE ...

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

...将输出:1, 2, 3, 4, 5

答案 4 :(得分:0)

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.