[英]how to pass local variables when assigning mouseover via anonymous function?
我有一個運行onload的設置函數,以向元素添加一些行為。 setup函數將參數傳遞給mouseover事件,但這些參數在for循環期間被更改,因為它們是本地引用。
function setupAreas( image, map, lots ) {
// obj is a simple wrapper for doc.getElementById
var image = obj(image); // image for imagemap
var map = obj(map); // imagemap element
var areas = map.getElementsByTagName('area');
for (var i in areas) {
var area = areas[i]; // imagemap area element
area.id = area.alt;
}
for (var lot_id in lots) {
if (lot_id != 'Lot No' && lot_id != '') {
var area = document.getElementById(lot_id);
if (!area || !area.coords) {
alert('no map coords for lot '+lot_id);
} else {
var coords = area.coords.split(",");
//alert('tag: '+area.tagName+' id: '+lot_id+' area: '+area);
var details = lots[lot_id];
if (details) {
// setup mouseover call with complete details of area
area.onmouseover = function(){ showLot(lot_id, area, coords, details, image, map, areas, lots) };
... snip ...
問題是因為for循環,每次迭代都會更改引用lot_id
和area
。 結果是任何元素的mouseover事件只給出了最后一個區域的lot_id
和區域。
我不想或不需要jQuery。 一個不污染全局命名空間的簡單JS解決方案是首選。
嘗試在閉包中包含for循環的內容:
for (var lot_id in lots) {
(function(lid){
//contents of for loop - use lid instead of lot_id
})(lot_id);
}
讓我知道這是如何工作的
編輯:你不必實際包圍整個循環,你可以只包圍附加事件的行:
(function(lid){
area.onmouseover = function(){ showLot(lid, area, coords, details, image, map, areas, lots) };
})(lot_id);
然而,圍繞整個循環可能會防止未來的錯誤:)
您需要在函數周圍創建一個閉包。 這樣的事情可能會有所幫助:
function makeShowLot(lot_id, area, coords, details, image, map, areas, lots) {
return function () {
showLot(lot_id, area, coords, details, image, map, areas, lots);
};
}
然后,改為:
area.onmouseover = makeShowLot(lot_id, area, coords, details, image, map, areas, lots);
makeShowLot
是一個返回函數的函數。 返回的函數不帶參數; showLot
所需的所有參數都包含在此匿名函數中。
正如你因為關閉而正確觀察到的那樣,'lot_id'被捕獲並且對於所有鼠標懸停事件都是相同的。
修復問題很簡單,在分配onmouseover之前,將lot_id存儲在另一個本地var中,比如lotIdForMouseOver,並將其傳遞給mouseover函數。
新的本地var將在C#中工作,而不是在JavaScript中。 在工作中,我做了很多C#,因此混亂!
像pkaeding建議的那樣,創建一個輔助函數,你應該很好。
另外,如果你'反''你的'if'檢查,你可以擺脫嵌套的ifs。 恕我直言,嵌套如果很難遵循。
這是我將如何做到這一點。
function setupAreas(image, map, lots)
{
// existing code
for(var lot_id in lots)
{
if(lot_id == 'Lot No' || lot_id == '')
continue;
var area = document.getElementById(lot_id);
if(!area || ! area.coords)
{
alert('no maps for coords for lot ' + lot_id);
continue;
}
var coords = area.coords.split(",");
var details = lots[lot_id];
if(! details)
continue;
//makeMouseOver function takes 'n' arguments and returns a function which
//will call showLot with those same 'n' arguments.
//This is the same suggestion as pkaeding, only that I have exploited 'arguments'
//property to make it simpler.
var makeMouseOver = function()
{
var creationArgs = arguments;
return function() { showLot.apply(null, creationArgs); };
}
area.onmouseover = makeMouseOver(lot_id, area, coords, details, image, map, area, lots);
// more code.
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.