2

Google Maps API を使用して、地図上にいくつかのポイントをプロットしています。ただし、以下のクリック イベント関数では、iは常に 4 に設定されます。つまり、ループを繰り返した後の値です。

// note these are actual addresses in the real page
var addresses = new Array( "addr 1", "addr 2", "addr 3", "addr 4" );

for (var i = 0; i < addresses.length; i++) {
    geocoder.getLatLng(addresses[i], function(point) {
        if (point) {
            var marker = new GMarker(point);
            map.addOverlay(marker);
            map.setCenter(point, 13);

            GEvent.addListener(marker, "click", function() {
                // here, i=4
                marker.openInfoWindowHtml("Address: <b>" + addresses[i] + "</b>");
            });
        }
    });
}

したがって、マーカーが表示されるときは、addresses[4]未定義の使用中です。の正しい値を関数に渡すにはどうすればよいiですか?

4

2 に答える 2

1

現在の反復中に無名関数を生成する必要があります。次の手順で修正する必要があります。

// note these are actual addresses in the real page 
var addresses = new Array( "addr 1", "addr 2", "addr 3", "addr 4" ); 

for (var i = 0; i < addresses.length; i++) { 
    geocoder.getLatLng(addresses[i], function (current) { 
        return function(point) { 
            if (point) { 
                var marker = new GMarker(point); 
                map.addOverlay(marker); 
                map.setCenter(point, 13); 

                GEvent.addListener(marker, "click", function() { 
                    // here, i=4 
                    marker.openInfoWindowHtml("Address: <b>" + addresses[current] + "</b>"); 
                }); 
            }
        } 
    }(i)); 
} 

B// これらは実際のページ内の実際のアドレスであることに注意してください var addresses = new Array( "addr 1", "addr 2", "addr 3", "addr 4" );

for (var i = 0; i < addresses.length; i++) { geocoder.getLatLng(addresses[i], function(point) { if (point) { var marker = new GMarker(point); map.addOverlay(marker) ; map.setCenter(点, 13);

        GEvent.addListener(marker, "click", function() { 
            // here, i=4 
            marker.openInfoWindowHtml("Address: <b>" + addresses[i] + "</b>"); 
        }); 
    } 
}); 

}

さらなる明確化
Google が提供 するgetLatLngメソッドは、ajax 呼び出しを使用して、特定の住所の緯度と経度を取得します。これは非同期呼び出しであり、現在のスレッドの一部ではないため、ajax 要求の完了時に呼び出されるコールバック関数が必要です。これは、関数の 2 番目のパラメーターとして指定する無名関数です。
ここで、ajax リクエストが作成されている間、コードは引き続き実行され、iループが配列を反復するたびに の値が増加します。最初の ajax 呼び出しが戻るまでに、ループはすでにアドレス配列の長さ (4) まで増加しているため、コールバック関数が実行iされると、ループによって増加した後にスコープ内の変数を取得しています。

私が書いた修正により、単一の引数を取り、変数を変数に置き換えcurrentた前の匿名関数を返す匿名関数を作成しています。この関数は、ループの次の繰り返しの前に、最初のパラメーターとして変数を使用してすぐに呼び出されます。これにより、関数が呼び出されたときに の現在の値が変数に格納されるクロージャーが作成されます。後で変数を参照すると、格納されている の値が取得されます。icurrentiicurrentcurrenti

私はこれらのことを説明するのがあまり得意ではありません。おそらく、私の理解が js Gods ほどよくないからです。javascript クロージャに関する詳細情報を読むことをお勧めします。

于 2010-01-19T18:25:27.233 に答える
-1

そのループで 4 に到達するべきではありません。ループは i < addresses.length (4) の間だけ実行されるため、ループは i=0 から i=3 まで実行する必要があります。

于 2010-01-19T18:25:26.187 に答える