2012-06-26 57 views
2

与谷歌地图的工作,我有以下代码:Javascript:在循环中定义一个函数时创建一个变量static?

var tileNames = ["base", "parking", "access"]; 
var mapType = {}; 

for (var i = 0; i < tileNames.length; i++) { 
    var tileOptions = { 
    getTileUrl: function(coord, zoom) { 
     return "/maps/tiles/tiles" + tileNames[i] + "/" + zoom + "_" + coord.x + "_" + coord.y + ".png"; 
    }, 
    tileSize: new google.maps.Size(256, 256) 
    }; 
mapType[tileNames[i]] = new google.maps.ImageMapType(tileOptions); 
}; 

这里是我的问题:“tileNames [I]”中的“getTileUrl”功能在执行功能时,是不确定的。然而,“tileNames”数组仅用于定义“mapType”对象,因此,与传递给函数的“coord”和“zoom”变量不同,我正在使用“tileNames [我]“来定义这部分功能。因此,理想情况下,分配给mapType.parking功能应该是这样的......

function(coord, zoom) { 
    return "/maps/tiles/tilesparking/" + zoom + "_" + coord.x + "_" + coord.y + ".png"; 
}; 

...该功能在第一段代码定义之后。有什么方法可以获取变量/数组的值,并使用它来静态定义一个函数,同时将其他两个变量保留为变量。


编辑:看着下面的各种答案,以下是我已经能够迄今为止达到最佳。虽然绑定可能是更普遍情况下的理想方法,但在这种特定情况下,“getTileUrl:”显然需要特定的语法,并将绑定放置在为其定义的函数上会导致Google Maps错误。在试用KGZM的建议时,它可以在任何情况下更新,而不是在IE8及更低版本中。

var tileNames = ["beloit", "parking", "access_p"]; 
var mapType = {}; 

for (var i = 0; i <= (tileNames.length - 1); i++) { 
    (function(i) { 
     tileOptions = { 
      getTileUrl: function(coord, zoom) { 
       return "/maps/tiles/tiles" + tileNames[i] + "/" + zoom + "_" + coord.x + "_" + coord.y + ".png"; 
      }, 
      tileSize: new google.maps.Size(256, 256) 
     }; 
     mapType[tileNames[i]] = new google.maps.ImageMapType(tileOptions); 
    })(i); 
}; 
+0

这是一个范围问题。在循环中定义函数往往会导致这个错误。在循环外定义你的函数,并按照flynfish的建议传入索引。 – Joe

+0

@JoeTuskan,这是一个迟到的回应,但他无法通过索引作为参数的原因是因为Google Maps API为他定义了这些函数的参数,这就是为什么我在下面建议“绑定”的原因。 –

回答

4

有一个函数式编程的概念,可以

基本上处理这很好,你的函数实际上有三个参数,zoom变量,则coord对象,以及tileNames[i]值,但是您希望tileNames[i]值在您的代码中一次固定为特定值,并将其他两个变量保留为实际变量。

function getTileUrlBuilder(tilename) { 
    return function(coord, zoom) { 
     return "/maps/tiles/tile" + tilename + "/" + zoom + "_" + coord.x + "_" + coord.y; 
    }; 
} 

然后你可以在你的循环中使用这个函数。然而,由于这实际上是一个常见的操作,您可以使用bind的方法来处理这个问题:

(function(tilename, coord, zoom) { 
    return "/maps/tiles/tile" + tilename + "/" + zoom + "_" + coord.x + "_" + coord.y 
}).bind(this, tileNames[i]); 

这将“绑定”隐this到当前this,然后第一个参数绑定到当前值tileNames[i]

编辑:这,我认为,应该是工作代码。

var tileNames = ["beloit", "parking", "access_p"]; 
var mapType = {}; 

function getTileUrlFull(tileName, coord, zoom) { 
    return "/maps2/tiles/tiles" + tileName + "/" + zoom + "_" + coord.x + "_" + coord.y + ".png" 
} 

for(var i = 0; i < tileNames.length; i++) { 
    mapType[tileNames[i]] = new google.maps.ImageMapType({ 
     getTileUrl: getTileUrlFull.bind(this, tileNames[i]), 
     tileSize: new google.maps.Size(256, 256) 
    }); 
} 
+0

绑定是IE9,但尽管如此。 – Joe

+0

@JoeTuskan,我忘记了那些不兼容。只需使用ES5垫片或者自己实现相对简单的''bind''方法即可。 –

+0

非常真实的投票。这里有一个垫片:https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind – Joe

1

你需要传递i到您getTileUrl功能:

getTileUrl: function(i, coord, zoom) { 
     return "/maps/tiles/tiles" + tileNames[i] + "/" + zoom + "_" + coord.x + "_" + coord.y + ".png"; 
    }, 
2

你需要另一种闭合。循环运行后,变量'i'的值为3. tileNames [3] =>未定义。但是你创建的每个函数都包含对同一个i变量的引用。

尝试这样:

for (var i = 0; i < tileNames.length; i++) { 
     (function(i) { 
     //loop body goes here. 
     })(i); 
    }; 
+0

这究竟是什么?它的作用大部分,但似乎不在IE9。这是戴维斯埃利斯建议的还是别的? –

+0

@TerraFimeira,它是一个闭包构造函数。循环中的每一个都会产生一个带有固定值的* new *''i''变量,而不是引用外层的''i''变量(即等于循环结尾的''tileNames.length'' )。 –

相关问题