web-dev-qa-db-ja.com

Javascriptのネストされた関数からの戻り値

私は次のように設定されている機能を持っています

function mainFunction() {
      function subFunction() {
            var str = "foo";
            return str;
      }
}

var test = mainFunction();
alert(test);

私の論理では、そのアラートは「foo」を返すはずですが、代わりに未定義を返します。何が間違っていますか?

[〜#〜] update [〜#〜]:これが私の実際のコードです(Google APIで逆ジオコーディングするための関数です)

function reverseGeocode(latitude,longitude){
    var address = "";
    var country = "";
    var countrycode = "";
    var locality = "";

    var geocoder = new GClientGeocoder();
    var latlng = new GLatLng(latitude, longitude);

     return geocoder.getLocations(latlng, function(addresses) {
     address = addresses.Placemark[0].address;
     country = addresses.Placemark[0].AddressDetails.Country.CountryName;
     countrycode = addresses.Placemark[0].AddressDetails.Country.CountryNameCode;
     locality = addresses.Placemark[0].AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName;
     return country;
    });   
   }
54
Chris Armstrong

何かを返す前に関数を呼び出す必要があります。

function mainFunction() {
      function subFunction() {
            var str = "foo";
            return str;
      }
      return subFunction();
}

var test = mainFunction();
alert(test);

または:

function mainFunction() {
      function subFunction() {
            var str = "foo";
            return str;
      }
      return subFunction;
}

var test = mainFunction();
alert( test() );

実際のコード用。戻り値は、メイン関数の外側にある必要があります。コールバックはgetLocationsメソッド内のどこかで呼び出されるため、その戻り値はメイン関数内で受信されません。

function reverseGeocode(latitude,longitude){
    var address = "";
    var country = "";
    var countrycode = "";
    var locality = "";

    var geocoder = new GClientGeocoder();
    var latlng = new GLatLng(latitude, longitude);

    geocoder.getLocations(latlng, function(addresses) {
     address = addresses.Placemark[0].address;
     country = addresses.Placemark[0].AddressDetails.Country.CountryName;
     countrycode = addresses.Placemark[0].AddressDetails.Country.CountryNameCode;
     locality = addresses.Placemark[0].AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName;
    });   
    return country
   }
60
z33m

右。 getLocations()に渡す関数は、データが使用可能になるまで呼び出されないため、設定される前に「国」を返すことは役に立ちません。

これを行うために必要な方法は、geocoder.getLocations()に渡す関数に、返された値で実行したいことを実際に実行させることです。

このようなもの:

function reverseGeocode(latitude,longitude){
  var geocoder = new GClientGeocoder();
  var latlng = new GLatLng(latitude, longitude);

  geocoder.getLocations(latlng, function(addresses) {
    var address = addresses.Placemark[0].address;
    var country = addresses.Placemark[0].AddressDetails.Country.CountryName;
    var countrycode = addresses.Placemark[0].AddressDetails.Country.CountryNameCode;
    var locality = addresses.Placemark[0].AddressDetails.Country.AdministrativeArea.SubAdministrativeArea.Locality.LocalityName;
    do_something_with_address(address, country, countrycode, locality);
  });   
}

function do_something_with_address(address, country, countrycode, locality) {
  if (country==="USA") {
     alert("USA A-OK!"); // or whatever
  }
}

位置を取得するたびに何か別のことをしたい場合は、関数を追加パラメーターとしてreverseGeocodeに渡します。

function reverseGeocode(latitude,longitude, callback){
  // Function contents the same as above, then
  callback(address, country, countrycode, locality);
}
reverseGeocode(latitude, longitude, do_something_with_address);

これが少し厄介に見える場合は、Dojoの遅延機能のようなものを見ることができます。これにより、関数間のチェーンが少し明確になります。

3
Mark Bessey

ちなみに、ジオコーダーは非同期であるため、論理的には受け入れられた答えはこのインスタンスでは実際には機能しません。アップデーターとして機能する外部オブジェクトが必要です。

var updater = {};

function geoCodeCity(goocoord) { 
    var geocoder = new google.maps.Geocoder();
    geocoder.geocode({
        'latLng': goocoord
    }, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
            updater.currentLocation = results[1].formatted_address;
        } else {
            if (status == "ERROR") { 
                    console.log(status);
                }
        }
    });
};
1
efwjames