Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/370.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么数组没有定义?_Javascript_Function_Google Maps_Callback - Fatal编程技术网

Javascript 为什么数组没有定义?

Javascript 为什么数组没有定义?,javascript,function,google-maps,callback,Javascript,Function,Google Maps,Callback,当我在geocoder函数外部警告我的数组“Markerary”时,它会说它未定义。 不知道为什么?有没有办法从函数外部的数组中获取值 var markerArray = new Array(); for(var i in opts.markers) { address = opts.markers[i].address; //alert(opts.markers[i].icon); var geocoder = new google.maps.Geocoder();

当我在geocoder函数外部警告我的数组“Markerary”时,它会说它未定义。
不知道为什么?有没有办法从函数外部的数组中获取值

var markerArray = new Array();
for(var i in opts.markers)
{
    address = opts.markers[i].address;
    //alert(opts.markers[i].icon);
    var geocoder = new google.maps.Geocoder();

    geocoder.geocode({ address: address }, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK && results.length) {
            if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
                map.setCenter(results[0].geometry.location);
                var marker = new google.maps.Marker({
                    position: results[0].geometry.location,
                    map: map
                });
            }
        }
        markerArray[i] = marker;

    });

}
alert(markerArray[0].position);

我怀疑它抱怨的不是
markerary
,而是
markerary[0]

您正在使用在循环中创建的函数调用异步API。这些函数是闭包。它们都有一个对
i
变量的持久引用,而不是定义函数时的值副本。因此,所有函数都使用循环中最后一个
i
值,因为它们在循环结束之前都不会运行。因此,如果循环中的最后一个值
i
5
,那么所有函数都将使用
5

而且,在任何回调有机会运行之前,您的
警报执行得太早了。您将需要在其中一个回调中执行您需要执行的任何最终处理(您可以使用计数器来知道它们何时发生)

您可以像这样修复
markerary
问题和过早的
警报

var markerArray = new Array();
var callcounter = 0;
for(var i in opts.markers)
{
    address = opts.markers[i].address;
    //alert(opts.markers[i].icon);
    var geocoder = new google.maps.Geocoder();

    ++callcounter;
    geocoder.geocode({ address: address }, buildCallback(i));

}

function buildCallback(index) {
    return function(results, status) {
        if (status == google.maps.GeocoderStatus.OK && results.length) {
            if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
                map.setCenter(results[0].geometry.location);
                var marker = new google.maps.Marker({
                    position: results[0].geometry.location,
                    map: map
                });
            }
        }
        markerArray[index] = marker;
        if (--callcounter === 0) {
            // This was the last outstanding call
            alert(markerArray[0]); // Always assuming there was a `0` in `opts.markers`
        }
    };
}
现在,回调是传递到
buildCallback
函数的
index
参数上的闭包,而不是主循环中的
i
变量。当我们完成所有回调时,我们会发出警报,这是因为
回调计数器
(如果您的“比赛条件”雷达关闭,请参阅下面的注释)

所有这些都是因为闭包的工作方式。它们并不复杂(事实上,我写了一篇关于它们的博客文章,名为),但有一些事情你需要坚定地理解,才能“理解”它们为什么这么做

分别:您正在使用
for..in
循环通过
opts.markers
,我怀疑这是一个数组。如果是,那么代码就有您需要解决的问题
for..in
不是用于循环遍历数组的索引,而是用于循环遍历对象的属性名称。您要么需要在
for..in
循环中添加一些检查,要么只使用一个无聊的老式
for
循环


关于
计数器
:对于任何习惯于多线程编程的人来说,我简单的“调度时递增,处理时递减”逻辑看起来像是设置了一个竞争条件(如果第一个在第二个调度之前被回调怎么办?)。但在浏览器上的JavaScript中,这不是竞争条件,因为浏览器上的JavaScript是单线程的(或者如果您使用多线程协作)。这里没有先发制人的多线程。在所有回调都被调度之前,不会调用它们



主题外:尽管
var markerArray=new Array()工作正常,我建议
var-markerArray=[]取而代之。它比较短;由于各种原因,实现可以进一步优化它(这并不重要);而且不可能有人跟踪了
数组
符号。类似地,任何时候只要一个空白对象,使用
{}
而不是
新对象()

选择数组或对象?这可能不会解决您的问题,但不要将
用于。。。在
中枚举数组:能否在markerary[i]=marker之后插入console.log(markerary);在警报之前呢?并显示结果。您可以在firebug或其他用于浏览器的javascript开发工具中监视console.log的输出。