Для-Каждый над массивом в JavaScript?

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

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

forEach(instance in theArray)

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

28 ответов


TL; DR

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

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

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


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

я быстро отмечу, что вы можете использовать опции ES2015 теперь, даже на двигателях ES5, by transpiling ES2015-ES5. Найдите "ES2015 transpiling" / "ES6 transpiling" для большего...

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

Для Реальных Массивов

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

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

детали:

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

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

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

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

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

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

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

кроме того, forEach является функцией "loop through them all", но ES5 определил несколько других полезных функций" work your way through the array and do things", включая:

  • every (останавливает цикл при первом возврате обратного вызова false или что-то falsey)
  • 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 воссоздается для каждой итерации цикла, что означает закрытие созданный в теле цикла сохранить ссылку на indexvalue) создан для этой конкретной итерации:

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

если бы у вас было пять divs, вы бы получили "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 будет следовать этому порядку. (Подробности в этот и другие ответы.)

все-таки это can быть полезным, особенно для редкие массивы, если вы используете соответствующие гарантии:

// `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. что ключ является базой-10 числовой строка в своей обычной Строковой форме и ее значение спецификации. Другие числа (нецелые, отрицательные числа, числа больше 2^32 - 2) не являются индексами массива. Причина 2^32 -2 это делает наибольшее значение индекса одним ниже, чем 2^32 -1, что является максимальным значением массива length can иметь. (Например, длина массива соответствует 32-разрядному целому числу без знака.) (реквизит для RobG для указания в комментарии на моем блоге что мой предыдущий тест был не совсем прав.)

это немного дополнительную нагрузку на каждой итерации цикла на большинстве массивов, но если у вас есть редкие array, это может быть более эффективный способ цикла, потому что он только петли для записей, которые на самом деле существуют. Например, для массива выше, мы цикл в общей сложности три раза (для ключей "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. Самый простой способ использовать итераторы-это new for-of заявление. Выглядит это так:

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

выход:

a
b
c

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

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

иногда вы можете использовать итератор явно. Вы тоже можете это сделать, хотя это намного неуклюже, чем for-of. Похоже это:

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

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

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

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

Массив-Как Объекты

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

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

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

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

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

    Предположим, вы хотите использовать 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 цикл

    очевидно, что простой for петля применяется для массивов объектов.

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

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

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

    for-of будет использовать итератор предоставляемые объектом (если таковые имеются); мы должны будем видеть, как это играет с различными массив-как объекты, особенно хозяин-обеспеченными. Например, спецификация для NodeList с querySelectorAll был обновлен для поддержки итерации. Спецификация для HTMLCollection с getElementsByTagName не было.

  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 в распространение синтаксис с движками JavaScript, которые поддерживают эту функцию:

    var trueArray = [...iterableObject];
    

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

    var divs = [...document.querySelectorAll("div")];
    
  3. использовать Array.from (spec) | (MDN)

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

    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 функции с хост-предоставлен array-like objects (списки DOM и другие вещи, предоставляемые браузером, а не движком JavaScript), вам нужно обязательно протестировать в целевых средах, чтобы убедиться, что объект, предоставленный хостом, ведет себя правильно. большинство ведут себя правильно (сейчас), но это важно для теста. Причина в том, что большинство Array.prototype методы, которые вы, вероятно, захотите использовать, полагаются на предоставленный хостом объект, дающий честный ответ на абстрактный [[HasProperty]] операции. На момент написания этой статьи браузеры делают очень хорошую работу, но спецификация 5.1 допускала возможность того, что объект, предоставленный хостом, может быть не честным. Это в §8.6.2, несколько абзацев ниже большой таблицы в начале этого раздела), где говорится:

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

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


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

  • forEach
  • карта
  • фильтр
  • zip
  • уменьшить
  • некоторые

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

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

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

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


Если вы используете jQuery библиотеки, вы можете использовать С помощью jQuery.каждый:

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

EDIT:

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

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

петли назад

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

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

плюсы:

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

недостатки:

  • оно обрабатывает детали в обратном порядке. Если вы строили новый массив из результатов или печатали вещи на экране, естественно выход будет обратный относительно первоначального заказа.
  • многократно вставляя братьев и сестер в DOM в качестве первого ребенка, чтобы сохранить их порядок менее эффективным!--44-->. (Браузеру придется все время что-то менять.) Чтобы создать узлы DOM эффективно и в порядке, просто выполните цикл вперед и добавьте как обычно (а также используйте "фрагмент документа").
  • обратный цикл сбивает с толку для младших разработчиков. (Вы можете считать, что преимущество, в зависимости от вашего мировоззрения.)

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

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

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

" просто сделайте это с каждым пунктом в списке, меня не волнует заказ!"

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

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

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

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

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

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

(если обсуждение намерения не имеет для вас смысла, то вы и ваш код можете извлечь выгоду из просмотра лекции Крокфорда на Стиль Программирования И Мозг!--64-->.)


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

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 что позволяет избежать каких-либо проблем с Array-out-of-bounds undefined предметы.

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

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

    фишка в том, что в отличие от --i трейлинг i-- декремента оператор i но возвращает значение до декремент. Ваша консоль может продемонстрировать следующее:

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

    [5, 5, 4]

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

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


Тривиа

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

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

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


некоторые C - языки стиля используют foreach для перебора перечислений. В JavaScript это делается с помощью for..in структура цикла:

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

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

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

дополнительно, ECMAScript 5 добавил forEach метод Array.prototype который можно использовать для перечисления по массиву с помощью calback (polyfill находится в документах, поэтому вы все еще можете использовать его для старых браузеров):

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

важно отметить, что Array.prototype.forEach не ломается, когда обратный вызов возвращается false. jQuery и подчеркивания.js обеспечить свои собственные вариации на each обеспечить петли которые можно закоротить.


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

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

вы можете получить некоторые оптимизации производительности путем кэширования myArray.length или повторяя его назад.


на forEach реализация (см. в 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
  }
);

если вы не возражаете опорожнить массив:

var x;

while(x = y.pop()){ 

    alert(x); //do something 

}

x будет содержать последнее значение y и он будет удален из массива. Вы также можете использовать shift() который даст и удалит первый элемент из y.


Я знаю, что это старый пост, и есть так много замечательных ответов уже. Для немного большей полноты я решил, что брошу еще один, используя AngularJS. Конечно, это применимо только в том случае, если вы используете Angular, очевидно, тем не менее я хотел бы поставить его в любом случае.

angular.forEach принимает 2 аргумента и необязательный третий аргумент. Первый аргумент-это объект (массив) для итерации, второй аргумент-функция итератора, а необязательный третий аргумент-это контекст объекта (в основном упоминается внутри цикла как "это".

существуют различные способы использования цикла forEach углового. Самый простой и, вероятно, наиболее используемый -

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

другой способ, который полезен для копирования элементов из одного массива в другой, -

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

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

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

теперь есть плюсы и минусы использования


простым решением сейчас было бы использовать подчеркивания.библиотека js. Он предоставляет множество полезных инструментов, таких как each и автоматически делегирует задание на native forEach если таковые имеются.

пример CodePen как это работает:

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

см. также


наверное for(i = 0; i < array.length; i++) петля не самый лучший выбор. Почему? Если у вас есть это:

var array = new Array();
array[1] = "Hello";
array[7] = "World";
array[11] = "!";

метод вызова от array[0] to array[2]. Во-первых, это будут первые ссылочные переменные, которых у вас даже нет, во-вторых, у вас не будет переменных в массиве, и в-третьих, это сделает код смелее. Смотри сюда, это то, что я использую:

for(var i in array){
    var el = array[i];
    //If you want 'i' to be INT just put parseInt(i)
    //Do something with el
}

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

function foreach(array, call){
    for(var i in array){
        call(array[i]);
    }
}

если вы хотите сломать, немного больше логика:

function foreach(array, call){
    for(var i in array){
        if(call(array[i]) == false){
            break;
        }
    }
}

пример:

foreach(array, function(el){
    if(el != "!"){
        console.log(el);
    } else {
        console.log(el+"!!");
    }
});

возвращает:

//Hello
//World
//!!!

существует три реализации foreach на jQuery следующим образом.

var a = [3,2];

$(a).each(function(){console.log(this.valueOf())}); //Method 1
$.each(a, function(){console.log(this.valueOf())}); //Method 2
$.each($(a), function(){console.log(this.valueOf())}); //Method 3

по состоянию на ES6:

list = [0, 1, 2, 3]
for (let obj of list) {
    console.log(obj)
}

здесь of избегает странностей, связанных с in и заставляет его работать как for цикл любого другого языка, и let персонализация i внутри цикла, а не внутри функции.

скобки ({}) можно опустить, если есть только одна команда (например, в приведенном выше примере).


нет for each цикл в native JavaScript. Вы можете использовать библиотеки для получения этой функции (я рекомендую подчеркивания.js), использовать простой for в петли.

for (var instance in objects) {
   ...
}

однако обратите внимание, что могут быть причины использовать еще более простой for loop (см. вопрос переполнения стека почему использование" for...in " с итерацией массива такая плохая идея?)

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

это итератор для разреженного списка, где индекс начинается с 0, что является типичным сценарием при работе с документом.getElementsByTagName или документ.querySelectorAll)

function each( fn, data ) {

    if(typeof fn == 'string')
        eval('fn = function(data, i){' + fn + '}');

    for(var i=0, L=this.length; i < L; i++) 
        fn.call( this[i], data, i );   

    return this;
}

Array.prototype.each = each;  

примеры использования:

Пример 1

var arr = [];
[1, 2, 3].each( function(a){ a.push( this * this}, arr);
arr = [1, 4, 9]

Пример #2

each.call(document.getElementsByTagName('p'), "this.className = data;",'blue');

каждый тег p получает class="blue"

Пример #3

each.call(document.getElementsByTagName('p'), 
    "if( i % 2 == 0) this.className = data;",
    'red'
);

каждый другой тег p получает class="red">

Пример 4

each.call(document.querySelectorAll('p.blue'), 
    function(newClass, i) {
        if( i < 20 )
            this.className = newClass;
    }, 'green'
);

и, наконец, первые 20 синих тегов p изменены на зеленый

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


здесь несколько способов для перебора массива в JavaScript, как показано ниже:

на - это самый распространенный. Полный блок кода для цикла

var languages = ["JAVA", "JavaScript", "C#", "Python"];
var i, len, text;
for (i = 0, len = languages.length, text = ""; i < len; i++) {
    text += languages[i] + "<br>";
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>

пока - цикл, пока условие выполнено. Кажется, это самый быстрый цикл

var text = "";
var i = 0;
while (i < 10) {
    text +=  i + ") something<br>";
    i++;
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>

do / while - также петля через a блок кода, пока условие истинно, будет выполняться хотя бы один раз

var text = ""
var i = 0;
do {
    text += i + ") something <br>";
    i++;
}
while (i < 10);
document.getElementById("example").innerHTML = text;
<p id="example"></p>

функциональные петли - forEach, map, filter, и reduce (они проходят через функцию, но используются, если вам нужно что-то сделать с вашим массивом и т. д.

// For example, in this case we loop through the number and double them up using the map function
var numbers = [65, 44, 12, 4];
document.getElementById("example").innerHTML = numbers.map(function(num){return num * 2});
<p id="example"></p>

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


нет встроенной возможности взломать forEach. Для прерывания выполнения используйте Array#some, как показано ниже:

[1,2,3].some(function(number) {
    return number === 1;
});

это работает, потому что some возвращает true, как только любой из обратных вызовов, выполненный в порядке массива, возвращает true, короткое замыкание выполнения остальных. Оригинальный Ответ см. прототип массива для некоторые


ECMAScript5 (версия на Javascript)для работы с массивами.

forEach - перебирает каждый элемент в массиве и делать все, что вам нужно с каждым элементом.

['C', 'D', 'E'].forEach(function(element, index) {
  console.log(element + " is the #" + (index+1) + " in musical scale");
});

// Output
// C is the #1 in musical scale
// D is the #2 in musical scale
// E is the #3 in musical scale

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

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

// Let's upper case the items in the array
['bob', 'joe', 'jen'].map(function(elem) {
  return elem.toUpperCase();
});

// Output: ['BOB', 'JOE', 'JEN']

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

[1,2,3,4].reduce(function(previous, current) {
  return previous + current;
});
// Output: 10
// 1st iteration: previous=1, current=2 => result=3
// 2nd iteration: previous=3, current=3 => result=6
// 3rd iteration: previous=6, current=4 => result=10

- возвращает true или false, если все элементы массива проходят тест в функции обратного вызова.

// Check if everybody has 18 years old of more.
var ages = [30, 43, 18, 5];  
ages.every(function(elem) {  
  return elem >= 18;
});

// Output: false

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

// Finding the even numbers
[1,2,3,4,5,6].filter(function(elem){
  return (elem % 2 == 0)
});

// Output: [2,4,6]

надеюсь, это будет полезно.


Я также хотел бы добавить это как композицию обратного цикла и ответ выше для кого-то, кто хотел бы этот синтаксис тоже.

var foo = [object,object,object];
for (var i = foo.length, item; item = foo[--i];) {
    console.log(item);
}

плюсы:

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

плюсы:

это сломается всякий раз, когда ссылка false-falsey (undefined, etc.). Это может быть использовано как преимущество. Тем не менее, это немного затруднит чтение. А также в зависимости от браузера он может быть " не " оптимизирован для работы быстрее, чем оригинальный.


jQuery с помощью $.map:

var data = [1, 2, 3, 4, 5, 6, 7];

var newData = $.map(data, function(element) {
    if (element % 2 == 0) {
        return element;
    }
});

// newData = [2, 4, 6];

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

myArray.forEach(
  (item) => {
    // do something 
    console.log(item);
  }
);

другой жизнеспособный способ - использовать Array.map() который работает таким же образом, но также mutates каждый элемент и возвращает его как:

var myArray = [1, 2, 3];
myArray = myArray.map(
  (item) => {
    return item + 1;
  }
);

console.log(myArray); // [2, 3, 4]

синтаксис лямбда обычно не работает в IE 10 или ниже.

Я обычно использую

[].forEach.call(arrayName,function(value,index){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});


If you are a jQuery Fan and already have a jQuery file running, you should reverse the positions of the index and value parameters

$("#ul>li").each(function(**index,value**){
    console.log("value of the looped element" + value);
    console.log("index of the looped element" + index);
});

var a = ["car", "bus", "truck"]
a.forEach(function(item, index) {
    console.log("Index" + index);
    console.log("Element" + item);
})

вы можете вызвать forEach следующим образом:

let Array = [1,3,2];

theArray.forEach((element)=>{ 
  // use the element of the array
  console.log(element) 
}

элемент будет иметь значение каждого индекса от 0 до длины массива.

выход:

1    
3    
2

объяснение:

forEach находится в классе прототипов. вы также можете назвать это как массив.прототип.инструкция foreach.(..);

прототип: https://hackernoon.com/prototypes-in-javascript-5bba2990e04b

вы также можете alterate за массив, как это:

for(let i=0;i<theArray.length;i++){
  console.log(i); //i will have the value of each index
}

если вы хотите использовать forEach(), Это будет выглядеть так -

theArray.forEach ( element => { console.log(element); });

если вы хотите использовать for(), это будет выглядеть так -

for(let idx = 0; idx < theArray.length; idx++){ let element = theArray[idx]; console.log(element); }


если у вас есть массив, вы должны использовать iterators чтобы получить некоторую эффективность. Итераторы являются свойством определенных коллекций JavaScript (например,Map, Set, String, Array). Даже,for..of использует iterator из-под капота.

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

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

преобразуйте свой обычный массив в итератор, используя values() способ такой:

    const myArr = [2,3,4]

let it = myArr.values();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

вы также можете преобразовать свой обычный массив в итератор, используя Symbol.iterator такой:

const myArr = [2,3,4]

let it = myArr[Symbol.iterator]();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

вы также можете преобразуйте свой обычный array до iterator такой:

let myArr = [8, 10, 12];

function makeIterator(array) {
    var nextIndex = 0;
    
    return {
       next: function() {
           return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
       }
    };
};

var it = makeIterator(myArr);

console.log(it.next().value);   // {value: 8, done: false}
console.log(it.next().value);   // {value: 10, done: false}
console.log(it.next().value);   // {value: 12, done: false}
console.log(it.next().value);   // {value: undefined, done: true}

Примечание:

  • итераторы являются исчерпываемыми по своей природе.
  • объекты не iterable по умолчанию. Использовать for..in в этом случае, потому что вместо ценностей он работает с ключами.

вы можете прочитать больше о iteration protocol здесь.


резюме:

при итерации по массиву мы часто можем хотеть выполнить одну из следующих целей:

  1. мы хотим перебрать массив и создать новый массив:

    Array.prototype.map

  2. мы хотим перебирать массив и не создавать новый массив:

    Array.prototype.forEach

    for..of цикл

в JS существует множество способов достижения обеих этих целей. Однако некоторые из них более условны, чем другие. Ниже вы можете найти некоторые часто используемые методы (наиболее традиционные imo) для выполнения итерации массива в javascript.

создание нового массива: Map

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

let arr = [1, 2, 3, 4, 5];

let newArr = arr.map((element, index, array) => {
  return element * 2;
})

console.log(arr);
console.log(newArr);

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

явная разница между map и другой механизм петли, как forEach и for..of петли, что map возвращает как новый массив и оставляет старый массив нетронутым (кроме тех случаев, когда вы эксплицитно манипулируете им с помощью thinks like splice).

также обратите внимание, что map обратный вызов функции предоставляет в качестве второго аргумента номер индекса текущей итерации. Кроме того, третий аргумент предоставляет массив, на котором map называлась. Иногда эти свойства могут быть очень полезны.

цикл с помощью forEach

forEach - это функция, которая находится на Array.prototype которая принимает функцию обратного вызова в качестве аргумента. Затем он выполняет эту функцию обратного вызова для каждого элемента массива. В отличие от map() функция функция forEach ничего не возвращает (undefined). Например:

let arr = [1, 2, 3, 4, 5];

arr.forEach((element, index, array) => {

  console.log(element * 2);

  if (index === 4) {
    console.log(array)
  }
  // index, and oldArray are provided as 2nd and 3th argument by the callback

})

console.log(arr);

как


function printList(callback) {
    // do your printList work
    console.log('printList is done');
    callback();
}

function updateDB(callback) {
    // do your updateDB work
    console.log('updateDB is done');
    callback()
}

function getDistanceWithLatLong(callback) {
    // do your getDistanceWithLatLong work
    console.log('getDistanceWithLatLong is done');
    callback();
}

function runSearchInOrder(callback) {
    getDistanceWithLatLong(function() {
        updateDB(function() {
            printList(callback);
        });
    });
}

runSearchInOrder(function(){console.log('finished')});

выход होगा getDistanceWithLatLong сделано команды updatedb делается printList сделано кончено