Javascript 通过匿名函数分配鼠标悬停时如何传递局部变量?

Javascript 通过匿名函数分配鼠标悬停时如何传递局部变量?,javascript,Javascript,我有一个运行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

我有一个运行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\u id
area
的引用都会发生变化。结果是任何元素的鼠标悬停事件只给出
批次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\u id”被捕获,并且对于所有鼠标悬停事件都是相同的。解决这个问题很简单,在分配onmouseover之前,将lot_id存储在另一个本地变量中,比如lotIdForMouseOver,并将其传递给mouseover函数。新的本地变量将在C#中工作,而不是在JavaScript中。在工作中,我做了很多C#,因此产生了混乱

就像pkaeding建议的那样,创建一个helper函数,您应该会很好

另一方面,如果你“反转”你的“如果”检查,你可以去掉嵌套的“如果”。 IMHO,嵌套的if很难遵循

我会这样做的

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.
    }
}

令人惊讶的是,我已经使用JS很多年了,从来都不知道闭包。