在函数javascript中调用函数

时间:2010-09-22 23:47:03

标签: javascript

我在jQuery ajax调用success: function(d)

的成功函数中有这个代码
for (var n in d.items)
{        
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() {
        focusMarker(d.items[n].id);
    });
}

不幸的是,该函数始终将d.items[n].id评估为d.items集合中的最后一项。

我尝试进行此修改:

for (var n in d.items)
{        
    var id = d.items[n].id;        
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() {
        focusMarker(id);
    });
}

但我的功能总是返回相同的东西。

这是范围问题,还是我的功能定义有问题?

5 个答案:

答案 0 :(得分:6)

有几种方法可以解决这个问题,最常见的是使用一个函数来保存循环值:

for (var n in d.items) {
  (function(id) {
    google.maps.event.addListener(markers[id], 'mouseover', function() {
        focusMarker(id);
    });
  })(d.items[n].id);
}

顺便说一句,如果d.items是一个数组,我建议你使用一个顺序循环,例如:

for (var n = 0; n < d.items.length; n++) {
  //..
}

for-in语句用于枚举对象属性。

如果您在数组或类似对象的数组上使用它,它可能会给您带来一些问题,首先,还会枚举继承的属性,这意味着如果有人扩充了Array.prototype对象,那么这些属性也将在您的枚举中枚举循环。

规范也不保证迭代的顺序,可能无法按数字顺序访问属性。

答案 1 :(得分:1)

你可以关闭:

for (var n in d.items)
{        
    (function(id) {        
      google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() {
          focusMarker(id);
      });
    })(d.items[n].id)
}

答案 2 :(得分:1)

这是范围问题。你想要做的是使用这样的闭包:

for (var n in d.items)
{        
    (function(id){
        google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() {
            focusMarker(id);
        });
    })(d.items[n].id);
}

答案 3 :(得分:1)

是的,这是一个范围问题,a very common one

封闭在闭包中的变量共享相同的单个环境,因此在调用mouseover回调时,for in循环将运行,n变量将留下指向它分配的最后一个值。

使用函数工厂可以解决更多闭包的问题:

function makeOnHoverHandler(id) {  
  return function () {  
    focusMarker(id);
  };  
}

// ...

for (var n in d.items) {        
  google.maps.event.addListener(markers[d.items[n].id], 
                                'mouseover', 
                                makeOnHoverHandler(d.items[n].id));
}

如果你不熟悉闭包的工作方式,这可能是一个非常棘手的话题。您可能需要查看以下Mozilla文章以获得简要介绍:

您也可以内联上述内容。这实际上是一种更常见的方法,但实际上与上述方法相同:

for (var n in d.items) {        
  google.maps.event.addListener(markers[d.items[n].id], 'mouseover', (function (id) {
    focusMarker(id);
  })(d.items[n].id));
}

任何另一个解决方案是通过使用自调用匿名函数将每个迭代包含在自己的范围内:

for (var n in d.items) {
  (function (id) {
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function () { 
      focusMarker(id);
    });
  })(d.items[n].id);
}

答案 4 :(得分:1)

与其他回复类似,但我认为内联定义内容更简洁,更简洁:

for (var n in d.items)
{        
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', new function() {
        return function() {
            focusMarker(d.items[n].id);
        }
    });
}

您可能想知道new function()的作用。它一次声明并执行一个函数。它基本上是简写:

for (var n in d.items)
{        
    google.maps.event.addListener(markers[d.items[n].id], 'mouseover', function() {
        return function() {
            focusMarker(d.items[n].id);
        }
    }());
}

虽然我认为第二个例子可能不起作用,因为如果你没有将结果赋给变量,你需要额外的括号。例如:

function() { alert("hi"); }();

语法错误。必须是:

(function() { alert("hi"); })();

作为函数参数内联是否算作赋值?我不知道。最好坚持我的第一个例子。