簡體   English   中英

如何通過匿名函數分配鼠標懸停時傳遞局部變量?

[英]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_idarea 結果是任何元素的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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM