做項目的時候,栽在一個小地方,是這樣的
我有很多個坐標點,我想把這些坐標點都綁定一個事件,當點擊了這個坐標點之后,發送一個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); }