将静态值传递给动态Javascript函数

Pass Static value to dynamic Javascript Function

本文关键字:动态 Javascript 函数 静态 值传      更新时间:2023-09-26

我确信这是一个简单的问题,但我一直没能弄清楚。下面显示了在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的闭包答案的增强版本:

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));
}

它采用四个参数并返回时间ID:

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