我有一个运行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解决方案。
答案 0 :(得分:2)
尝试在闭包中包含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);
然而,围绕整个循环可以防止将来出现的错误:)
答案 1 :(得分:2)
您需要在函数周围创建一个闭包。这样的事情可能会有所帮助:
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
所需的所有参数都包含在这个匿名函数中。
答案 2 :(得分:0)
正如您因为关闭而正确观察时,捕获了'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.
}
}