2010-09-22 15 views
1

我有一個jQuery AJAX調用success: function(d)調用JavaScript的

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].idd.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); 
    }); 
} 

但我的函數總是返回同樣的事情。

這是一個範圍問題,還是有我的函數定義有什麼問題?

回答

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聲明是爲了用於枚舉了對象屬性。

如果在陣列或類似陣列的對象上使用它,它會給你帶來一些問題,首先,繼承的屬性也被枚舉,這意味着如果有人擴充了對象,那麼這些屬性也將在你的循環中被枚舉。

此外,規範不保證迭代次序,可能不會按數字順序訪問屬性。

+0

謝謝,完美的工作! – Zahymaka 2010-09-23 01:16:53

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

是否內嵌作爲函數參數計數作爲賦值?我不知道。更好地堅持我的第一個例子。