js循环里进行回调,引用循环里的变量,发现只是最后值的问题

做项目的时候,栽在一个小地方,是这样的 

我有很多个坐标点,我想把这些坐标点都绑定一个事件,当点击了这个坐标点之后,发送一个ajax 请求,将坐标点的id 发出去,等待显示返回的数据

但是实际当中,无论我点击了哪个点,都发现发送的ajax 请求都是最后一个点的id值上,

仔细一想,确实是这么回事,因为点击这个事情是异步,当执行ajax的时候,遍历早已结束,所以返回最后一点是正常的。

 

问题变成了,怎样让回调函数读取到每次的临时变量,也就是个闭包的问题

平时对闭包不是太清楚,所以顺便复习一下了,

参考资料也是博客园朋友写的   http://kb.cnblogs.com/page/110782/

之后也参考了这里 http://stackoverflow.com/questions/6978911/closure-inside-a-for-loop-callback-with-loop-variable-as-parameter

这里大概这么处理

在循环里写

function build_callback(id){
  
returnfunction(data, textStatus){ alert(id);
  };
}
$.get("XXXX",build_callback(id))


 

也可以使用匿名函数解决

for (var idx=1; idx<=15; idx++)
    (function(idx) {
        var probeIP = siteConfigArray[idx].siteIP;
        if (probeIP != "" && probeIP != null)
            jQuery.get("svGetPortInfo.php?svSiteIpAddr=" + probeIP+"&s="+idx, 
                function(data, textStatus) { test(data, textStatus, idx); }, 'text'); 
        else // IP value is blank
            siteConfigArray[idx].portManifest = null;
    })(idx);

 

最后,如果有人用coffeescript 来写,那就变得更简单了,只需要在循环里在加一句 do (XXX) ->   

coffeescript就会自动生成好闭包,这里是我的代码

for node in stations 
      do (node) ->
        point = new BMap.Point(node.lng,node.lat)
        marker = new BMap.Marker(point)
        label = new BMap.Label(node.name, {offset: new BMap.Size(20, 4)})
        marker.setLabel(label)
            
        contextMenu = new BMap.ContextMenu()
        contextMenu.addItem(new BMap.MenuItem("查看 #{node.name} 详情", () ->                                                                                      
          $.get("stations/#{node.id}",(data)->
            eval data 
          )   

        , 200))
        window.map.addOverlay(marker)
        marker.addContextMenu(contextMenu)

 

coffeescript 也给出了官方例子 
for filename in list
  do (filename) ->
    fs.readFile filename, (err, contents) ->
      compile filename, contents.toString()

会对应生成这样的js

var filename, _fn, _i, _len;

_fn = function(filename) {
  return fs.readFile(filename, function(err, contents) {
    return compile(filename, contents.toString());
  });
};
for (_i = 0, _len = list.length; _i < _len; _i++) {
  filename = list[_i];
  _fn(filename);
}

 

 

 

posted @ 2014-02-11 10:15 Atpking 阅读(...) 评论(...) 编辑 收藏