代码之家  ›  专栏  ›  技术社区  ›  SpliFF

通过匿名函数分配mouseover时如何传递局部变量?

  •  3
  • SpliFF  · 技术社区  · 15 年前

    我有一个设置函数,它运行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事件 洛特伊德 和面积 最后一个区域 .

    我不想也不需要jquery。首选不污染全局命名空间的简单JS解决方案。

    3 回复  |  直到 15 年前
        1
  •  2
  •   Darko    15 年前

    尝试在一个闭包中围绕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);
    

    但是,围绕整个循环可能会阻止将来出现错误:)

        2
  •  2
  •   pkaeding    15 年前

    您需要围绕您的函数创建一个闭包。类似这样的事情可能会有所帮助:

    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 包含在这个匿名函数中。

        3
  •  0
  •   SolutionYogi Eric Lippert    15 年前

    正如您正确地观察到的,由于关闭,“lot_id”被捕获,并且对于所有mouseover事件都是相同的。 解决这个问题很简单,在分配onMouseOver之前,将lot_id存储在另一个本地var中,比如lotidformouseOver,并将其传递给mouseOver函数。 新的本地变量将在C_中工作,而不是在JavaScript中。在工作中,我做了很多C因此产生了混乱!

    像建议的pkading一样,创建一个助手函数,您应该很好。

    另一方面,如果您“反转”您的“if”检查,则可以除去嵌套的if。 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.
        }
    }