несколько вопросов, когда итератор массивоподобный объект в JavaScript - PullRequest
0 голосов
/ 11 февраля 2012

В моем приложении мне нужно выполнить некоторые итерации с массивоподобным объектом.

Поэтому я пишу собственный метод util:

Util.forEach=function(iterator,callback,context){
  if(iterator.length){
    for(var i=0;i<iterator.length;i++){
      var val=iterator[i];
      callback && callback.call(context||null,val,i);
    }
  }
}

Тогда я сталкиваюсь с некоторыми проблемами:

Предположим, у меня есть массив: var ary = [1,2,3,4,5];

1. как разорвать петлю?

Например, если я хочу узнать, включено ли значение '2' в массив, я могу попробовать это:

Util.forEach(ary,function(value,index){
  if(value==2){
    //find mached value,now I should break and return this value.

    //but I can not use 'break' in this context.
  }
});

2. удалить значение массива при использовании итератора

Если я хочу удалить значение '2' из массива, я могу попробовать это:

Util.forEach(ary,function(value,index){
  if(value==2){
    //delete it.
    ary.splice(i,1);
    // I wonder if this is the safe way?
  }
});

Поскольку в Java мы не можем сделать это при итерации массива, это вызовет исключение параллелизма.

Хотя я запускаю приведенный выше код без каких-либо ошибок, но я не уверен, что это лучший метод?

Ответы [ 3 ]

1 голос
/ 11 февраля 2012

Как правило, вы можете выйти из метода forEach, используя try - catch и throw.

var value = 'Not Found';
try {
    Util.forEach(ary, function(value, index) {
       if(value == 2) {
           throw value; //<-- Throw the found result: Terminates current forEach
       }
    });
} catch (found) {       // Catch the thrown result
    value = found;
}
0 голосов
/ 11 февраля 2012

как разорвать петлю?

Ты не должен выходить из forEach. Вот почему это называется «для каждого», а не «для некоторых». "Breakable" итераторы JS: every() (останавливается, когда обратный вызов возвращает false) и some() (останавливается, когда обратный вызов возвращает true).

Еще раз взглянув на ваш код, я думаю, что вам нужен метод indexOf, а не итератор.

удалить значение массива при использовании итератора

Итераторы не должны вносить никаких изменений в базовый массив. Вы должны реализовать filter() и использовать его для генерации нового массива.

См. js итерационные методы для более подробной информации.

0 голосов
/ 11 февраля 2012

Первая проблема может быть решена путем проверки возвращаемого значения из обратного вызова и остановки итерации, если она возвращает false.Затем вы можете остановить итерацию, вернув false из обратного вызова.Возврат чего-либо кроме false (включая ничего не возвращая) продолжит итерацию.jQuery использует этот метод возврата значения, чтобы отменить итерацию в их .each() итераторе.Если добавить это в свой код, это будет выглядеть так:

Util.forEach=function(iterator,callback,context){
    if (iterator.length && callback) {
        for(var i = 0; i < iterator.length; i++){
            var val=iterator[i];
            if (callback.call(context||window,val,i) === false) {
                break;
            }
        }
    }
}

В документации MDN для forEach вы можете увидеть пример реализации.

На второмвопрос, этот тип реализации не разрешает вставку или удаление элементов в точке итерации или до нее, потому что это приведет к тому, что некоторые элементы будут пропущены во время итерации, или некоторые объекты будут повторяться несколько раз.Очевидный способ обойти это - сделать копию объекта перед итерацией, что неэффективно, когда не нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...