簡體   English   中英

將靜態值傳遞給動態 Javascript 函數

[英]Pass Static value to dynamic Javascript Function

我相信這是一個簡單的問題,但一直無法弄清楚。 下面顯示了在mousedown事件上創建並添加到谷歌地圖標記的函數。 這是為每個迭代的標記創建的。

我不知道的部分是在pickupVenue(data[i].id)下面的第5行,在這個函數調用中提交的值總是最后一個迭代值。 我想在創建每個標記時在我迭代的內容中粘貼一個靜態值。

for (i in data) {
    google.maps.event.addListener(marker, 'mousedown', function() {
        state = PINCH;
        map.setOptions({draggable: false});
        timeoutId = setTimeout(function() { pickupVenue(data[i].id) }, 1000); 
    });
}

---- 工作結果 ----

google.maps.event.addListener(marker, 'mousedown', pickupMarker(data[i].Listing.id));

function pickupMarker(id) {
    return function() {
        state = PINCH;
        map.setOptions({draggable: false});
        timeoutId = setTimeout('pickupVenue('+id+')', 1000);
    }
}

您需要確保作為事件偵聽器傳遞的函數在其范圍內有一個變量,該變量引用了i在循環中持有的值而沒有被修改i被修改。

當前,您在循環中創建的所有函數都共享相同的i變量,因此當最終調用處理程序時,它們最終都會獲得i引用的任何值。

在 JavaScript 中,創建新變量作用域的唯一方法是調用一個函數,並在該函數中創建一個引用所需值的局部變量(或參數)。

像這樣:

function createListener( i ) {
    return function() {
        state = PINCH;
        map.setOptions({draggable: false});
        timeoutId = setTimeout(function() { pickupVenue(data[i].id) }, 1000); 
    };
}

for (i in data) {
    google.maps.event.addListener(marker, 'mousedown', createListener( i ) );
}

在這里,我創建了一個createListener()函數,並將i傳遞給它。

因為您的偵聽器函數現在是在createListener()函數內創建的,該偵聽器將引用該變量范圍內的i ,它將繼續保留調用createListener()時給定的任何值(除非您的函數修改i )。

然后createListener()返回該偵聽器函數,該函數作為第三個參數傳遞給addListener()

IAbstractDownvoteFactor's Closure answer的增強版本:

for (i in data) {
    google.maps.event.addListener(marker, 'mousedown', function() {
        state = PINCH;
        map.setOptions({draggable: false});

        var timeoutFn = function(theId) {
            return function realTimeoutFn() {
                pickupVenue(theId); // value of "theId" is kept
            };
        };

        timeoutId = setTimeout(timeoutFn(data[i].id), 1000); 
    });
}

我看到setTimeout()經常出現這個問題,記住正確的閉包語法總是很麻煩,所以我想也許我們應該創建一個setTimeoutWithData()實用程序函數,使這變得非常簡單。 所以這里是:

function setTimeoutWithData(rock, fn, t, ctx) {
    ctx = ctx || window;
    function localFn() {
        fn.call(ctx, rock);
    }
    return(setTimeout(localFn, t));
}

它接受四個參數並返回 timerID:

rock

這是將傳遞給您的回調的任何類型的任何數據。 如果你想傳遞大量數據,你可以讓岩石成為一個對象或一個數組。

fn

這是你的回調函數。 它將作為參數傳遞給岩石,因此您的回調應該像這樣聲明: function fn(rock) {}

t

這是以毫秒為單位的 setTimeout 時間值,與 setTimeout 相同。

ctx

這是唯一的可選參數。 如果您希望您的回調具有特定的this值,您可以使用 ctx 參數進行配置。 除其他外,這允許您使用 setTimeoutWithData 來調用對象上的方法並適當地設置this方法,以便更輕松地使用面向對象的編程。 如果 ctx 沒有通過,那么this將被設置為window (與 setTimeout 相同)。

因此,此處原始問題中的問題將這樣解決:

for (i in data) {
    google.maps.event.addListener(marker, 'mousedown', function() {
        state = PINCH;
        map.setOptions({draggable: false});
        timeoutId = setTimeoutWithData(data[i].id, function(anID) { pickupVenue(anID) }, 1000); 
    });
}

而且,這里有一個示例應用程序,顯示了這個實用程序函數: http : //jsfiddle.net/jfriend00/3SUAJ/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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