Возвращаемое значение из вложенной функции в Javascript

У меня есть функция, которая устанавливается следующим образом

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

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

В свою логику это предупреждение должно возвращать 'foo', но вместо этого возвращает undefined. Что я делаю неправильно?

UPDATE: здесь мой фактический код (это функция для обратного геокодирования с API Google)

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

Ответ 1

вам нужно вызвать функцию, прежде чем она сможет что-то вернуть.

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
   }

Ответ 2

Right. Функция, которую вы передаете 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

Просто FYI, геокодер является асинхронным, поэтому принятый ответ в то время как логический не работает в этом случае. Я бы предпочел иметь внешний объект, который действует как ваш обновитель.

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