Вопрос: Для каждого по массиву в JavaScript?


Как я могу перебирать все записи в массиве с помощью JavaScript?

Я думал, что это что-то вроде этого:

forEach(instance in theArray)

где theArrayэто мой массив, но это кажется неправильным.


3706


источник


Ответы:


TL; DR

  • Не использовать for-inесли вы не используете его с гарантиями или, по крайней мере, не знаете, почему он может вас укусить.
  • Ваши лучшие ставки обычно

    • for-of(только ES2015 +),
    • Array#forEach( spec| MDN) (или его родственников someи такие) (только ES5 +),
    • простой старомодный forпетли,
    • или for-inс гарантиями.

Но есть много больше, чтобы исследовать, читать дальше ...


JavaScript имеет мощную семантику для циклического преобразования массивов и объектов типа массива. Я разделил ответ на две части: опции для подлинного массива и варианты для вещей, как , такой как argumentsобъект, другие итерируемые объекты (ES2015 +), коллекции DOM и т. д.

Я быстро заметлю, что вы можете использовать опции ES2015 Теперь , даже на двигателях ES5, transpiling ES2015 - ES5. Найдите «ES2015 transpiling» / «ES6 transpiling» для более ...

Хорошо, давайте посмотрим на наши варианты:

Для реальных массивов

У вас есть три варианта: ECMAScript 5 («ES5»), версия, наиболее широко поддерживаемая на данный момент, и в скором времени будет еще две ECMAScript 2015 («ES2015», «ES6»), последняя версия JavaScript, на которой производители работают над поддержкой:

  1. использование forEachи связанные (ES5 +)
  2. Используйте простой forпетля
  3. использование for-in правильно
  4. использование for-of(используйте итератор неявно) (ES2015 +)
  5. Использовать итератор явно (ES2015 +)

Детали:

1. Использовать forEachи связанные

Если вы используете среду, поддерживающую Arrayфункции ES5 (напрямую или с помощью прокладки), вы можете использовать новый forEach( spec| MDN):

var a = ["a", "b", "c"];
a.forEach(function(entry) {
    console.log(entry);
});

forEachпринимает функцию итератора и, необязательно, значение для использования в качестве thisпри вызове этой функции итератора (не используется выше). Функция итератора вызывается для каждой записи в массиве, чтобы пропустить несуществующие записи в разреженных массивах. Хотя я использовал только один аргумент выше, функция итератора вызывается с тремя: значение каждой записи, индекс этой записи и ссылка на массив, который вы повторяете (в случае, если ваша функция еще не имеет этого удобно).

Если вы не поддерживаете устаревшие браузеры, такие как IE8 (которые NetApps показывает на уровне более 4% рынка на момент написания этой статьи в сентябре 2016 года), вы можете с радостью использовать forEachна универсальной веб-странице без прокладки. Если вам нужна поддержка устаревших браузеров, то обрезка / полипирование forEach(поиск «es5 shim» для нескольких опций).

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

Если вы беспокоитесь о затратах времени выполнения вызова функции для каждой записи массива, не будьте; Детали ,

Дополнительно, forEachявляется функцией «loop through them all», но ES5 определил несколько других полезных «проработайте свой путь через массив и делайте», в том числе:

  • every(прерывает цикл при первом возвращении итератора falseили что-то ложное)
  • some(прерывает цикл при первом возвращении итератора trueили что-то правдоподобное)
  • filter(создает новый массив, включающий элементы, в которые возвращается функция фильтра trueи опускать те, где он возвращается false)
  • map(создает новый массив из значений, возвращаемых функцией итератора)
  • reduce(создает значение путем повторного вызова итератора, передавая предыдущие значения, см. спецификацию для деталей, полезно для суммирования содержимого массива и многих других вещей)
  • reduceRight(как reduce, но работает в нисходящем, а не восходящем порядке)

2. Используйте простой forпетля

Иногда старые способы являются лучшими:

var index;
var a = ["a", "b", "c"];
for (index = 0; index < a.length; ++index) {
    console.log(a[index]);
}

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

var index, len;
var a = ["a", "b", "c"];
for (index = 0, len = a.length; index < len; ++index) {
    console.log(a[index]);
}

И / или считая назад:

var index;
var a = ["a", "b", "c"];
for (index = a.length - 1; index >= 0; --index) {
    console.log(a[index]);
}

Но с современными механизмами JavaScript редко вам нужно выкупить этот последний сок.

В ES2015 и выше вы можете сделать свой индекс и переменные значений локальными forцикл:

let a = ["a", "b", "c"];
for (let index = 0; index < a.length; ++index) {
    let value = a[index];
}
//console.log(index); // Would cause "ReferenceError: index is not defined"
//console.log(value); // Would cause "ReferenceError: value is not defined"

И когда вы это делаете, не только valueно также indexвоссоздается для каждой итерации цикла, то есть замыкания, созданные в теле цикла, содержат ссылку на index(а также value), созданный для этой конкретной итерации:

let divs = document.querySelectorAll("div");
for (let index = 0; index < divs.length; ++index) {
    divs[index].addEventListener('click', e => {
        alert("Index is: " + index);
    });
}

Если у вас было пять div, вы бы получили «Index is: 0», если вы нажали первый и «Index is: 4», если вы нажали последний. Это делает не работать, если вы используете varвместо let,

3. Использование for-in правильно

Вы заставите людей говорить вам использовать for-in, но это не то, что for-inдля , for-inпетли через перечислимые свойства объекта , а не индексы массива. Заказ не гарантируется , даже в ES2015 (ES6). ES2015 определяет свойства объекта для объекта (через [[OwnPropertyKeys]], [[Enumerate]], и вещи, которые используют их, как Object.getOwnPropertyKeys), но это не определить, что for-inбудет следовать этому порядку. (Подробности в этот другой ответ .)

Тем не менее, это Можно быть полезными, особенно для редкий массивы , если вы используете соответствующие меры предосторожности:

// `a` is a sparse array
var key;
var a = [];
a[0] = "a";
a[10] = "b";
a[10000] = "c";
for (key in a) {
    if (a.hasOwnProperty(key)  &&        // These are explained
        /^0$|^[1-9]\d*$/.test(key) &&    // and then hidden
        key <= 4294967294                // away below
        ) {
        console.log(a[key]);
    }
}

Обратите внимание на две проверки:

  1. То, что объект имеет свой своя свойство по этому имени (не одно, которое оно наследует от своего прототипа), и

  2. То, что ключ представляет собой числовую строку base-10 в своей обычной строковой форме, и ее значение <= 2 ^ 32 - 2 (что составляет 4 294 967 294). Откуда это число? Это часть определения индекса массива в спецификации , Другие числа (нецелые числа, отрицательные числа, числа больше 2 ^ 32 - 2) не являются индексами массива. Причина в том, что это 2 ^ 32 - 2 заключается в том, что наибольшее значение индекса составляет менее 2 ^ 32 - 1 , которое является максимальным значением массива lengthмогу иметь. (Например, длина массива соответствует 32-разрядному целому числу без знака.) (Подставка к RobG для указания в комментарии на моем сообщении в блоге что мой предыдущий тест был не совсем прав.)

Это крошечный бит добавленных накладных расходов на каждую итерацию цикла на большинстве массивов, но если у вас есть редкий массив, это может быть более эффективным способом для цикла, потому что он только петли для записей, которые на самом деле существуют. Например, для массива, приведенного выше, мы суммируем три раза (для ключей "0", "10", а также "10000"- помните, это строки), а не 10 001 раз.

Теперь вы не захотите писать это каждый раз, так что вы можете поместить это в свой инструментарий:

function arrayHasOwnIndex(array, prop) {
    return array.hasOwnProperty(prop) && /^0$|^[1-9]\d*$/.test(prop) && prop <= 4294967294; // 2^32 - 2
}

И тогда мы будем использовать его так:

for (key in a) {
    if (arrayHasOwnIndex(a, key)) {
        console.log(a[key]);
    }
}

Или, если вас интересует только тест «достаточно хороший для большинства случаев», вы можете использовать это, но пока оно близко, это не совсем правильно:

for (key in a) {
    // "Good enough" for most cases
    if (String(parseInt(key, 10)) === key && a.hasOwnProperty(key)) {
        console.log(a[key]);
    }
}

4. Использовать for-of(используйте итератор неявно) (ES2015 +)

ES2015 добавляет итераторы к JavaScript. Самый простой способ использовать итераторы - это новый for-ofзаявление. Это выглядит так:

var val;
var a = ["a", "b", "c"];
for (val of a) {
    console.log(val);
}

Вывод:

б
с 

Под обложками итератор из массива и проходит через него, получая от него значения. Это не означает, что использование for-inимеет, поскольку он использует итератор, определенный объектом (массивом), а массивы определяют, что их итераторы итерации проходят через их записи (а не их свойства). В отличие от for-inв ES5 порядок, в котором просматриваются записи, - это числовой порядок их индексов.

5. Используйте итератор явно (ES2015 +)

Иногда вы можете использовать итератор эксплицитно , Вы тоже можете это сделать, хотя это намного clunkier, чем for-of, Это выглядит так:

var a = ["a", "b", "c"];
var it = a.values();
var entry;
while (!(entry = it.next()).done) {
    console.log(entry.value);
}

Итератор является функцией (в частности, генератор ), который возвращает новый объект при каждом вызове next, Объект, возвращаемый итератором, имеет свойство, done, рассказывая нам, сделано ли это, и имущество valueсо значением для этой итерации.

Значение valueварьируется в зависимости от итератора; массивы поддерживают (по крайней мере) три функции, возвращающие итераторы:

  • values(): Это тот, который я использовал выше. Он возвращает итератор, где каждый valueэто значение для этой итерации.
  • keys(): Возвращает итератор, где каждый valueявляется ключом к этой итерации (так для нашего aвыше, это будет "0", тогда "1", тогда "2").
  • entries(): Возвращает итератор, где каждый valueпредставляет собой массив в форме [key, value]для этой итерации.

(На момент написания статьи Firefox 29 поддерживал entriesа также keysно нет values.)

Для объектов, подобных массиву

Помимо истинных массивов, существуют также массив типа объекты, имеющие lengthсвойство и свойства с числовыми именами: NodeListслучаев, argumentsобъект и т. д. Как мы просматриваем их содержимое?

Используйте любой из вышеперечисленных параметров для массивов

По крайней мере некоторые и, возможно, большинство или даже все из вышеперечисленных массивов часто применяются одинаково хорошо для объектов типа массива:

  1. использование forEachи связанные (ES5 +)

    Различные функции Array.prototypeявляются «преднамеренно генерическими» и обычно могут использоваться для объектов типа массива через Function#callили Function#apply, (См. Предостережение для объектов, предоставляемых хостом в конце этого ответа, но это редкий вопрос.)

    Предположим, вы хотели использовать forEachна Node«s childNodesимущество. Вы сделали бы это:

    Array.prototype.forEach.call(node.childNodes, function(child) {
        // Do something with `child`
    });
    

    Если вы собираетесь сделать это много, вы можете захотеть захватить копию ссылки на функцию в переменную для повторного использования, например:

    // (This is all presumably in some scoping function)
    var forEach = Array.prototype.forEach;
    
    // Then later...
    forEach.call(node.childNodes, function(child) {
        // Do something with `child`
    });
    
  2. Используйте простой forпетля

    Очевидно, что простой forloop применяется к подобным массиву объектам.

  3. использование for-in правильно

    for-inс теми же гарантиями, что и с массивом, должен работать и с подобными массиву объектами; может потребоваться оговорка для объектов, предоставленных хостом, на № 1 выше.

  4. использование for-of(используйте итератор неявно) (ES2015 +)

    for-ofбудет использовать итератор, предоставляемый объектом (если таковой имеется); мы должны будем увидеть, как это происходит с различными подобными массивом объектами, особенно с хост-файлами.

  5. Использовать итератор явно (ES2015 +)

    См. № 4, нам нужно посмотреть, как разворачиваются итераторы.

Создать истинный массив

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

  1. Использовать sliceметод массивов

    Мы можем использовать sliceметод массивов, который, как и другие методы, упомянутые выше, является «преднамеренно общим» и поэтому может использоваться с подобными массиву объектами, например:

    var trueArray = Array.prototype.slice.call(arrayLikeObject);
    

    Так, например, если мы хотим конвертировать NodeListв настоящий массив, мы могли бы сделать это:

    var divs = Array.prototype.slice.call(document.querySelectorAll("div"));
    

    См. Предостережение для объектов, предоставляемых хостом ниже. В частности, обратите внимание, что это не удастся в IE8 и ранее, что не позволяет использовать объекты, предоставленные хостом, как thisкак это.

  2. использование спред обозначения ( ...)

    Также возможно использовать ES2015 разметка (MDN в настоящее время называет это оператором, это не одно), с механизмами JavaScript, которые поддерживают эту функцию:

    var trueArray = [...iterableObject];
    

    Так, например, если мы хотим конвертировать NodeListв настоящий массив, с синтаксисом распространения это становится довольно кратким:

    var divs = [...document.querySelectorAll("div")];
    
  3. использование Array.from (Спецификация) | (MDN)

    Array.from(ES2015, но shimmable) создает массив из объекта, подобного массиву, в случае необходимости сначала передавая записи через функцию сопоставления. Так:

    var divs = Array.from(document.querySelectorAll("div"));
    

    Или, если вы хотите получить массив имен тегов для элементов с заданным классом, вы должны использовать функцию сопоставления:

    // Arrow function (ES2015):
    var divs = Array.from(document.querySelectorAll(".some-class"), element => element.tagName);
    
    // Standard function (since `Array.from` can be shimmed):
    var divs = Array.from(document.querySelectorAll(".some-class"), function(element) {
        return element.tagName;
    });
    

Предостережение для объектов, предоставляемых хостом

Если вы используете Array.prototypeфункции с хозяйничать, при условии массивные объекты (списки DOM и другие вещи, предоставляемые браузером, а не движком JavaScript), вы должны обязательно протестировать в своих целевых средах, чтобы убедиться, что объект, обеспечивающий хост, ведет себя правильно. Большинство из них ведут себя правильно (сейчас), но важно проверить. Причина в том, что большая часть Array.prototypeметоды, которые вы, вероятно, захотите использовать, полагаются на предоставленный хостом объект, давая честный ответ на абстрактный [[HasProperty]]операция. На момент написания этой статьи браузеры очень хорошо справились с этим, но спецификация ES5 позволила предположить, что объект, предоставляемый хостом, может быть не честным; Оно в §8.6.2 (несколько абзацев ниже большой таблицы в начале этого раздела), где говорится:

Хост-объекты могут реализовывать эти внутренние методы любым способом, если не указано иное; например, одна из возможностей заключается в том, что [[Get]]а также [[Put]]для определенного объекта хоста действительно извлекают и сохраняют значения свойств, но [[HasProperty]]всегда генерирует ложный ,

(Я не мог найти эквивалентную формулировку в спецификации ES2015, но она все еще имеет место.) Опять же, на момент написания общих объектов, подобных хосту, в современных браузерах (например, NodeListэкземпляры, например) делать ручка [[HasProperty]]правильно, но важно проверить.


5889



редактировать : Этот ответ безнадежно устарел. Для более современного подхода взгляните на методы, доступные на массиве , Способы, представляющие интерес, могут быть:

  • для каждого
  • карта
  • фильтр
  • застежка-молния
  • уменьшить
  • каждый
  • некоторые

Стандартный способ итерации массива в JavaScript ваниль for-loop:

var length = arr.length,
    element = null;
for (var i = 0; i < length; i++) {
  element = arr[i];
  // Do something with element i.
}

Обратите внимание, однако, что этот подход хорош только при наличии плотного массива, и каждый индекс занят элементом. Если массив разрежен, то вы можете столкнуться с проблемами производительности с этим подходом, поскольку вы будете перебирать множество индексов, которые не действительно существуют в массиве. В этом случае for .. in-Лоп может быть лучшей идеей. Однако , вы должны использовать соответствующие меры предосторожности, чтобы гарантировать, что действуют только желаемые свойства массива (то есть элементы массива), поскольку for..in-loop также будет перечисляться в устаревших браузерах или если дополнительные свойства определяются как enumerable,

В ECMAScript 5 для прототипа массива будет использоваться метод forEach, но он не поддерживается в старых браузерах. Поэтому, чтобы иметь возможность использовать его последовательно, вы должны либо иметь среду, которая его поддерживает (например, Node.js для JavaScript на стороне сервера) или используйте «Polyfill». Однако Polyfill для этой функции тривиальна, и поскольку она упрощает чтение кода, это хороший полиполк.


444



Если вы используете JQuery библиотеки, вы можете использовать jQuery.each :

$.each(yourArray, function(index, value) {
  // do your stuff here
});

РЕДАКТИРОВАТЬ :

В соответствии с вопросом пользователь хочет код в javascript вместо jquery, поэтому редактирование

var length = yourArray.length;   
for (var i = 0; i < length; i++) {
  // Do something with yourArray[i].
}

203



Петля назад

я думаю задний ход для цикла заслуживает упоминания здесь:

for (var i = array.length; i--; ) {
     // process array[i]
}

Преимущества:

  • Вам не нужно объявлять временный lenпеременная или сравнивать с array.lengthна каждой итерации, любой из которых может быть минутной оптимизацией.
  • Удаление братьев и сестер из DOM в обратном порядке, как правило, более эффективным , (Браузеру необходимо меньше перемещать элементы во внутренних массивах).
  • если ты изменить массив при циклировании, в или после индекса я (например, вы удаляете или вставляете элемент в array[i]), тогда передняя петля пропускает элемент, который сдвинут влево в положение я , или повторно обработать я который был сдвинут вправо. В традиционном для цикла, вы мог Обновить я чтобы указать на следующий элемент, который нуждается в обработке - 1, но просто изменить направление итерации часто проще а также более элегантное решение ,
  • Аналогичным образом, при изменении или удалении вложенными Элементы DOM, обработка в обратном порядке обходить ошибки , Например, рассмотрите возможность изменения внутреннегоHTML родительского узла перед обработкой его дочерних элементов. К моменту достижения дочернего узла он будет отделен от DOM, заменив его новым созданным потомком, когда был записан внутренний HTTML родителя.
  • это короче для ввода и читать , чем некоторые другие доступные опции. Хотя он теряет forEach()и для ES6 for ... of,

Недостатки:

  • Он обрабатывает элементы в обратном порядке. Если вы строили новый массив из результатов или печатали на экране, естественно выход будет отменен в отношении первоначального порядка.
  • Неоднократно вставляя братьев и сестер в DOM в качестве первого ребенка, чтобы сохранить их порядок, менее эффективны , (Браузеру все равно придется менять вещи.) Чтобы создать узлы DOM эффективно и упорядоченно, просто переходите вперед и добавьте как обычно (а также используйте «фрагмент документа»).
  • Обратная петля запутанным для младших разработчиков. (Вы можете учесть это преимущество, в зависимости от вашего прогноза.)

Должен ли я всегда использовать его?

Некоторые разработчики используют обратное для цикла по умолчанию , если нет веских оснований для перемотки вперед.

Хотя прирост производительности обычно незначителен, это крики:

«Просто сделайте это для каждого элемента в списке, я не забочусь о заказе!»

Однако на практике это не на самом деле, надежное указание на намерение, поскольку оно неотличимо от тех случаев, когда вы делать заботиться о заказе и действительно делать необходимость для обратной петли. Таким образом, на самом деле потребуется еще одна конструкция, чтобы точно выразить намерение «не заботиться», то, что в настоящее время недоступно на большинстве языков, включая ECMAScript, но которое можно было бы назвать, например, forEachUnordered(),

Если заказ не имеет значения, и эффективность является проблемой (в самом внутреннем цикле движка игры или анимации), тогда может быть приемлемым использовать обратный цикл для цикла как ваш шаблон. Просто помните, что просмотр обратного цикла в существующем коде не обязательно означает что порядок не имеет значения!

Лучше использовать forEach ()

В общем, для кода более высокого уровня, где ясности и безопасности более серьезные проблемы, я бы рекомендовал использовать Array::forEachкак ваш шаблон по умолчанию:

  • Ясно читать.
  • Это указывает на то, что я не будет перемещаться внутри блока (что всегда является возможным сюрпризом, скрывающимся в длинных forа также whileпетли).
  • Это дает вам свободу действий для закрытия.
  • Это уменьшает утечку локальных переменных и случайное столкновение с (и мутацией) внешних переменных.

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

(Если обсуждение намерения не имеет для вас никакого смысла, вам и вашему коду может быть полезно наблюдать за лекцией Крокфорда о Стиль программирования и ваш мозг .)


Как это работает?

for (var i = 0; i < array.length; i++) { ... }   // Forwards

for (var i = array.length; i--; )    { ... }   // Reverse

Вы заметите, что i--это среднее предложение (где мы обычно видим сравнение), а последнее предложение пусто (где мы обычно видим i++). Что означает, что i--также используется в качестве состояние для продолжения. Реально, он выполнен и проверен до каждая итерация.

  • Как это можно начинать с array.lengthбез взрыва?

    Потому как i--работает до каждой итерации, на первой итерации мы фактически будем обращаться к элементу на array.length - 1что позволяет избежать любых проблем с Массив-недоступный undefinedПредметы.

  • Почему он не останавливает итерацию перед индексом 0?

    Цикл прекратит итерацию, когда условие i--оценивает значение false (когда оно дает 0).

    Фокус в том, что в отличие от --i, конечный i--уменьшение оператора iно дает значение до декремент. Ваша консоль может продемонстрировать это:

    > var i = 5; [i, i--, i];

    [5, 5, 4]

    Итак, на последней итерации, я ранее 1 и i--выражение меняет его на 0 но фактически дает 1 (правдивый), и поэтому условие проходит. На следующей итерации i--изменения я в -1 но дает 0 (falsey), в результате чего выполнение немедленно выйдет из нижней части цикла.

    В традиционном forwards for loop, i++а также ++iявляются взаимозаменяемыми (как указывает Дуглас Крокфорд). Однако в обратном для цикла, поскольку наш декремент также является выражением нашего условия, мы должны придерживаться i--если мы хотим обработать элемент с индексом 0.


пустяки

Некоторым людям нравится нарисовать маленькую стрелу на оборотной стороне forпетля и конец с подмигиванием:

for (var i = array.length; i --> 0 ;) {

Кредиты идут в WYL, чтобы показать мне преимущества и ужасы обратного цикла.


85



Some C-style languages use foreach to loop through enumerations. In JavaScript this is done with the for..in loop structure:

var index,
    value;
for (index in obj) {
    value = obj[index];
}

There is a catch. for..in will loop through each of the object's enumerable members, and the members on its prototype. To avoid reading values that are inherited through the object's prototype, simply check if the property belongs to the object:

for (i in obj) {
    if (obj.hasOwnProperty(i)) {
        //do stuff
    }
}

Additionally, ECMAScript 5 has added a forEach method to Array.prototype which can be used to enumerate over an array using a calback (the polyfill is in the docs so you can still use it for older browsers):

arr.forEach(function (val, index, theArray) {
    //do stuff
});

It's important to note that Array.prototype.forEach doesn't break when the callback returns false. jQuery and Underscore.js provide their own variations on each to provide loops that can be short-circuited.


67



If you want to loop over an array, use the standard three-part for loop.

for (var i = 0; i < myArray.length; i++) {
    var arrayItem = myArray[i];
}

You can get some performance optimisations by caching myArray.length or iterating over it backwards.


29



A forEach implementation (see in jsFiddle):

function forEach(list,callback) {
  var length = list.length;
  for (var n = 0; n < length; n++) {
    callback.call(list[n]);
  }
}

var myArray = ['hello','world'];

forEach(
  myArray,
  function(){
    alert(this); // do something
  }
);

25



I know this is an old post, and there are so many great answers already. For a little more completeness I figured I'd throw in another one using AngularJS. Of course, this only applies if you're using Angular, obviously, nonetheless I'd like to put it anyway.

angular.forEach takes 2 arguments and an optional third argument. The first argument is the object (array) to iterate over, the second argument is the iterator function, and the optional third argument is the object context (basically referred to inside the loop as 'this'.

There are different ways to use the forEach loop of angular. The simplest and probably most used is

var temp = [1, 2, 3];
angular.forEach(temp, function(item) {
    //item will be each element in the array
    //do something
});

Another way that is useful for copying items from one array to another is

var temp = [1, 2, 3];
var temp2 = [];
angular.forEach(temp, function(item) {
    this.push(item); //"this" refers to the array passed into the optional third parameter so, in this case, temp2.
}, temp2);

Though, you don't have to do that, you can simply do the following and it's equivalent to the previous example:

angular.forEach(temp, function(item) {
    temp2.push(item);
});

Now there are pros and cons of using the angular.forEach function as opposed to the built in vanilla-flavored for loop.

Pros

  • Easy readability
  • Easy writability
  • If available, angular.forEach will use the ES5 forEach loop. Now, I will get to efficientcy in the cons section, as the forEach loops are much slower than the for loops. I mention this as a pro because it's nice to be consistent and standardized.

Consider the following 2 nested loops, which do exactly the same thing. Let's say that we have 2 arrays of objects and each object contains an array of results, each of which has a Value property that's a string (or whatever). And let's say we need to iterate over each of the results and if they're equal then perform some action:

angular.forEach(obj1.results, function(result1) {
    angular.forEach(obj2.results, function(result2) {
        if (result1.Value === result2.Value) {
            //do something
        }
    });
});

//exact same with a for loop
for (var i = 0; i < obj1.results.length; i++) {
    for (var j = 0; j < obj2.results.length; j++) {
        if (obj1.results[i].Value === obj2.results[j].Value) {
            //do something
        }
    }
}

Granted this is a very simple hypothetical example, but I've written triple embedded for loops using the second approach and it was very hard to read, and write for that matter.

Cons

  • Efficiency. angular.forEach, and the native forEach, for that matter, are both so much slower than the normal for loop....about 90% slower. So for large data sets, best to stick to the native for loop.
  • No break, continue, or return support. continue is actually supported by "accident", to continue in an angular.forEach you simple put a return; statement in the function like angular.forEach(array, function(item) { if (someConditionIsTrue) return; }); which will cause it to continue out of the function for that iteration. This is also due to the fact that the native forEach does not support break or continue either.

I'm sure there's various other pros and cons as well, and please feel free to add any that you see fit. I feel that, bottom line, if you need efficiency, stick with just the native for loop for your looping needs. But, if your datasets are smaller and a some efficiency is okay to give up in exchange for readability and writability, then by all means throw an angular.forEach in that bad boy.


25



If you don't mind emptying the array:

var x;

while(x = y.pop()){ 

    alert(x); //do something 

}

x will contain the last value of y and it will be removed from the array. You can also use shift() which will give and remove the first item from y.


24



An easy solution now would be to use the underscore.js library. It's providing many useful tools, such as each and will automatically delegate the job to the native forEach if available.

A CodePen example of how it works is:

var arr = ["elemA", "elemB", "elemC"];
_.each(arr, function(elem, index, ar)
{
...
});

See also


22