Функции обратного вызова JavaScript и рекурсия

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

15
задан Shadow The Princess Wizard 1 May 2012 в 07:57
поделиться

4 ответа

Другие ответы хороши, но вот еще одна опция. Это позволяет Вам сохранять ту же форму, с которой Вы запустили, но используете прием именования Вашей функции лямбды так, чтобы можно было обратиться к нему рекурсивно:

mapstrings = ['mapstring1', 'mapstring2', 'mapstring3'];

geocoder.getLatLng(mapstrings.shift(), function lambda(point) {
   if(point) {
        // success
        map.setCenter(point, 13);
        map.setZoom(7);
        map.addOverlay(new GMarker(point));
    }
    else if(mapstrings.length > 0) {
        // Previous mapstring failed... try next mapstring
        geocoder.getLatLng(mapstrings.shift(), lambda);
    }
    else {
        // Take special action if no mapstring succeeds?
    }
})

В первый раз, когда символ "лямбда" используется, это должно представить его как новое функциональное литеральное имя. Во второй раз, когда это используется, это - рекурсивная ссылка.

функциональное литеральное именование работает в Chrome, и я предполагаю, что это работает в большинстве современных браузеров, но я не протестировал его, и я не знаю о более старых браузерах.

21
ответ дан 1 December 2019 в 01:54
поделиться

Как насчет этого?

function place_point(mapstrings,idx)
{
    if(idx>=mapstrings.length) return;
    geocoder.getLatLng(mapstrings[idx],
                       function(point)
                       {
                           if(!point)
                           {
                               place_point(mapstrings,idx+1);
                               return;
                           }
                           map.setCenter(point, 13);
                           map.setZoom(7);
                           map.addOverlay(new GMarker(point));
                       });
}

столько резервного копирования представляет в виде строки, сколько Вы хотите. Просто назовите его с 0 как второй аргумент в первый раз.

1
ответ дан 1 December 2019 в 01:54
поделиться

Да, факторизуйте его в функцию :)

geocoder.getLatLng(item.mapstring, function(point) {
    if (!point) {
        geocoder.getLatLng(item.backup_mapstring, function(point) {
                if (point) {
                    setPoint(point);
                }
        })
        return;
    }

    function setPoint(point) {
        map.setCenter(point, 13);
        map.setZoom(7);
        map.addOverlay(new GMarker(point));
    }

    setPoint(point);
});
2
ответ дан 1 December 2019 в 01:54
поделиться

Существует чрезвычайно хороший метод для выполнения рекурсии в конструкциях языка, которые явно не поддерживают рекурсию, названную комбинатор неподвижной точки . Самое известное Y-Combinator.

Вот Y combinator для функции одного параметра в Javascript:

function Y(le, a) {
    return function (f) {
        return f(f);
    }(function (f) {
        return le(function (x) {
            return f(f)(x);
        }, a);
    });
}

Это выглядит немного страшным, но только необходимо записать что однажды. Используя его на самом деле довольно просто. В основном Вы берете свою исходную лямбду одного параметра, и Вы превращаете его в новую функцию двух параметров - первый параметр является теперь фактическим лямбда-выражением, на котором можно сделать рекурсивный вызов, второй параметр является исходным первым параметром (point), что Вы хотите использовать.

Это - то, как Вы могли бы использовать его в своем примере. Обратите внимание, что я использую mapstrings в качестве списка строк для поиска, и поп-функция пагубно удалила бы элемент от главы.

geocoder.getLatLng(pop(mapstrings), Y(
  function(getLatLongCallback, point)
  {
    if (!point)
    {
      if (length(mapstrings) > 0)
        geocoder.getLatLng(pop(mapstrings), getLatLongCallback);
      return;
    }

    map.setCenter(point, 13);
    map.setZoom(7);
    map.addOverlay(new GMarker(point));
  });
8
ответ дан 1 December 2019 в 01:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: