Javascript:在循环中定义函数时使变量成为静态?

时间:2012-06-26 19:41:28

标签: javascript string function google-maps variables

使用Google地图,我有以下代码:

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

这是我的问题:执行该函数时,“getTileUrl”函数中的“tileNames [i]”未定义。但是,“tileNames”数组仅用于定义“mapType”对象,因此,与传递给函数的“coord”和“zoom”变量不同,我希望使用“tileNames [我]“定义函数的那一部分。因此,理想情况下,分配给mapType.parking的函数看起来像这样......

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

...在第一段代码中定义函数之后。有没有办法获取变量/数组的值并使用它来静态定义函数,同时将其他两个变量保持为变量。


编辑:查看下面的各种答案,以下是迄今为止我能够取得的最佳成绩。虽然在更一般的情况下绑定可能是理想的方法,但在这种特定情况下,“getTileUrl:”显然需要特定的语法,并且在为其定义的函数周围放置绑定会导致映射错误。在尝试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);
};

3 个答案:

答案 0 :(得分: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)
    });
}

答案 1 :(得分:2)

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

尝试这样的事情:

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

答案 2 :(得分:1)

您需要将i传递到getTileUrl函数:

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