所以我确信这是一个简单的问题但是无法解决这个问题。下面显示了在'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);
}
}
答案 0 :(得分:2)
您需要确保您传递的函数作为事件侦听器在其作用域中有一个变量,该变量引用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
,这将继续保留调用{{1}时给出的任何值。 1}}(除非你的函数修改createListener()
)。
然后i
返回该侦听器函数,该函数作为第三个参数传递给createListener()
。
答案 1 :(得分:1)
来自IAbstractDownvoteFactor的Closure答案的增强版:
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);
});
}
答案 2 :(得分:0)
我看到setTimeout()
这个问题频繁出现,记住正确的闭包语法总是很麻烦,所以我想也许我们应该创建一个setTimeoutWithData()
实用函数,这样可以很容易。所以这就是:
function setTimeoutWithData(rock, fn, t, ctx) {
ctx = ctx || window;
function localFn() {
fn.call(ctx, rock);
}
return(setTimeout(localFn, t));
}
它需要四个参数并返回timerID:
rock
这是任何类型的数据都将传递给您的回调。如果你想传递大量数据,你可以将rock变成一个对象或一个数组。
fn
这是你的回调函数。它将作为参数传递给rock,因此你的回调应该像这样声明:function fn(rock) {}
t
这是以ms为单位的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/。