Для каждого над массивом в JavaScript?

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

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

forEach(instance in theArray)

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

46 ответов

Решение

TL;DR

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

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

Но есть еще много интересного, читайте дальше...


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

Я быстро отмечу, что теперь вы можете использовать опции ES2015, даже на двигателях ES5, перенеся 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 (напрямую или с использованием полифилл), вы можете использовать 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 это функция "проходить через них все", но 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);
    });
}

Если бы у вас было пять делений, вы бы получили "Индекс: 0", если вы щелкнули по первому, и "Индекс: 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. Что ключ является числовой строкой из 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+)

Иногда вы можете явно использовать итератор. Вы можете сделать это тоже, хотя это гораздо более неловко, чем 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 со значением для этой итерации. (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, (См. Caveat для предоставленных хостом объектов в конце этого ответа, но это редкая проблема.)

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

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

  2. Использовать распространенный синтаксис ( ... )

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

    var trueArray = [...iterableObject];
    

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

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

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

    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]] операция. На момент написания статьи браузеры отлично справлялись с этой задачей, но спецификация 5.1 действительно допускала вероятность того, что предоставленный хостом объект может быть не честным. Это в §8.6.2, несколько параграфов под большой таблицей в начале этого раздела), где написано:

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

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

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

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

Стандартный способ итерации массива в 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может быть лучшей идеей Тем не менее, вы должны использовать соответствующие меры предосторожности, чтобы гарантировать, что только требуемые свойства массива (то есть, элементы массива) действуют, так как for..in-loop также будет перечисляться в устаревших браузерах, или если дополнительные свойства определены как enumerable,

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

Если вы используете библиотеку 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].
}

Петля назад

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

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

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

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

Недостатки:

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

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

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

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

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

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

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

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

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

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

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

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


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

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-- оценивает к значению Falsey (когда это дает 0).

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

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

    [5, 5, 4]

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

    В традиционных форвардах для цикла, 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 который может быть использован для перечисления по массиву с помощью функции обратного вызова (polyfill находится в документации, поэтому вы все еще можете использовать его для старых браузеров):

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

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

for ... of, forEach и карта

Использование современного синтаксиса javascript

      const fruits = ['🍎', '🍋', '🍌', '🍉']


👉🏽 for...of

for (const fruit of fruit) {
    console.log(fruit)
}

// '🍎', '🍋', '🍌', '🍉'


👉🏽 forEach

fruits.forEach(fruit => { 
    console.log(fruit) 
})

// '🍎', '🍋', '🍌', '🍉'


👉🏽 map

fruits.map(fruit => fruit)

// ['🍎', '🍋', '🍌', '🍉']

ВАЖНО: Обычно вы хотите, чтобы map () что-то возвращала, это делает ее идеальной функцией для преобразования массивов.

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

СОВЕТ: вы также можете иметь индекс (а также весь массив) на каждой итерации в ваших функциях .map () или .forEach(). Просто передайте им дополнительные аргументы:

      fruits.map((fruit, i) =>  i + '  ' + fruit)

// ['0 🍎', '1 🍋', '2 🍌', '3 🍉']



fruits.forEach((f, i, arr) => {
    console.log( f + ' ' + i + ' ' +  arr )
})

// 🍎 0 🍎, 🍋, 🍌, 🍉
// 🍋 1 🍎, 🍋, 🍌, 🍉
// 🍌 2 🍎, 🍋, 🍌, 🍉
// 🍉 3 🍎, 🍋, 🍌, 🍉

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

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

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

Если вы не против очистки массива:

var x;

while(x = y.pop()){ 

    alert(x); //do something 

}

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

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

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

Есть разные способы использования цикла forEach angular. Самый простой и, вероятно, самый используемый

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

Теперь есть плюсы и минусы использования angular.forEach функция в отличие от встроенного ванильного со вкусом for петля.

Pros

  • Легко читаемость
  • Простота записи
  • Если доступно, angular.forEach будет использовать цикл ES5 forEach. Теперь я доберусь до эффективности в разделе "против", поскольку циклы forEach намного медленнее, чем циклы for. Я упоминаю это как профессионал, потому что приятно быть последовательным и стандартизированным.

Рассмотрим следующие 2 вложенных цикла, которые делают одно и то же. Допустим, у нас есть 2 массива объектов, и каждый объект содержит массив результатов, каждый из которых имеет свойство Value, являющееся строкой (или чем-то еще). И скажем, нам нужно перебрать каждый из результатов и, если они равны, выполнить некоторое действие:

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

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

Cons

  • Эффективность. angular.forEachи родной forEachв этом отношении оба гораздо медленнее, чем обычно for цикл.... примерно на 90% медленнее. Так что для больших наборов данных лучше придерживаться нативных for петля.
  • Без перерыва, продолжения или возврата поддержки. continue на самом деле поддерживается " аварии", чтобы продолжить в angular.forEach ты просто положил return; утверждение в функции, как angular.forEach(array, function(item) { if (someConditionIsTrue) return; }); что заставит его продолжать выходить из функции для этой итерации. Это также связано с тем, что родной forEach не поддерживает перерыв или продолжить.

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

Реализация 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
  }
);

Начиная с ES6:

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

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

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

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

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

Метод будет вызываться из array[0] в 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

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

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

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

Смотрите также

  • Документация для родныхArray.prototype.forEach(),
  • В for_each... в (MDN) объясняется, что for each (variable in object) не рекомендуется как часть стандарта ECMA-357 ( EAX).
  • for... of (MDN) описывает следующий способ итерации с использованием for (variable of object) как часть предложения Harmony (ECMAScript 6).

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

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

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

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

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

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

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

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

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

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

[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

Every - Возвращает 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

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

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

// Output: [2,4,6]

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

Это итератор для не разреженного списка, где индекс начинается с 0, что является типичным сценарием при работе с document.getElementsByTagName или document.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');

Каждый р-тег получает class="blue"

Пример № 3

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

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

Пример № 4

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

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

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

Есть несколько способов перебрать массив в 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>

while - цикл пока условие выполнено. Вроде бы самая быстрая петля

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

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

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: отображение, фильтрация и уменьшение.

Используйте, где это возможно

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

Синтаксис

      const nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (const num of nums) {
  /* Do something with num */
}

Видетьссылка на дополнительные примеры, ссылка на спецификацию и разницу междуfor...ofиfor...in. Или, может быть, посмотрите этот учебник для объяснения того, чем они отличаются.

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

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

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

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

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

Плюсы:

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

Минусы:

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

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

Использование циклов с оператором деструктуризации и распространения ES6

Разрушение и использование оператора распространения оказались весьма полезными для новичков в ES6 как более удобочитаемые / эстетичные, хотя некоторые ветераны javascript могут посчитать это грязным, юниоры или некоторые другие люди могут найти его полезным.

Следующие примеры будут использовать for...of заявление и .forEach метод.

Примеры 6, 7 и 8 могут использоваться с любыми функциональными циклами, такими как .map, .filter, .reduce, .sort, .every, .some За дополнительной информацией об этих методах обращайтесь к объекту Array.

Пример 1: Нормальный for...of петля - никаких хитростей здесь.

let arrSimple = ['a', 'b', 'c'];

for (let letter of arrSimple) {
  console.log(letter);
}

Пример 2: разделение слов на символы

let arrFruits = ['apple', 'orange', 'banana'];

for (let [firstLetter, ...restOfTheWord] of arrFruits) {
  // Create a shallow copy using the spread operator
  let [lastLetter] = [...restOfTheWord].reverse();
  console.log(firstLetter, lastLetter, restOfTheWord);

}

Пример 3: цикл с key а также value

// let arrSimple = ['a', 'b', 'c'];

// Instead of keeping an index in `i` as per example `for(let i = 0 ; i<arrSimple.length;i++)`
// this example will use a multi-dimensional array of the following format type: 
// `arrWithIndex: [number, string][]`

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Same thing can be achieved using `.map` method
// let arrWithIndex = arrSimple.map((i, idx) => [idx, i]);

// Same thing can be achieved using `Object.entries`
// NOTE: `Object.entries` method doesn't work on internet explorer unless it's polyfilled
// let arrWithIndex = Object.entries(arrSimple);

for (let [key, value] of arrWithIndex) {
  console.log(key, value);
}

Пример 4: Получить свойства объекта встроенными

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];

for (let { name, age: aliasForAge } of arrWithObjects) {
  console.log(name, aliasForAge);
}

Пример 5: Получить глубокие свойства объекта того, что вам нужно

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

for (let { name, tags: [firstItemFromTags, ...restOfTags] } of arrWithObjectsWithArr) {
  console.log(name, firstItemFromTags, restOfTags);
}

Пример 6: Используется ли Пример 3 с .forEach

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Not to be confused here, `forEachIndex` is the real index
// `mappedIndex` was created by "another user", so you can't really trust it

arrWithIndex.forEach(([mappedIndex, item], forEachIndex) => {
  console.log(forEachIndex, mappedIndex, item);
});

Пример 7: Используется ли Пример 4 с .forEach

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];
// NOTE: Destructuring objects while using shorthand functions 
// are required to be surrounded by parenthesis
arrWithObjects.forEach( ({ name, age: aliasForAge }) => {
  console.log(name, aliasForAge)
});

Пример 8: Пример 5 используется с .forEach

let arrWithObjectsWithArr = [{
    name: 'Jon',
    age: 32,
    tags: ['driver', 'chef', 'jogger']
  },
  {
    name: 'Elise',
    age: 33,
    tags: ['best chef', 'singer', 'dancer']
  }
];

arrWithObjectsWithArr.forEach(({
  name,
  tags: [firstItemFromTags, ...restOfTags]
}) => {
  console.log(name, firstItemFromTags, restOfTags);
});

Производительность

Сегодня (2019-12-18) я выполнить тест на моем Macos v10.13.6 (High Sierra), на Chrome против 79,0, Safari v13.0.4 и Firefox v71.0 (64 бит) - выводы об оптимизации (и микро-оптимизации, которые обычно не стоит вводить его в код, потому что польза небольшая, но сложность кода растет).

  • Похоже на традиционный for i(Aa) - хороший выбор для написания быстрого кода во всех браузерах.

  • Другие решения, например for-of(Ad), все в группе C.... обычно в 2 - 10 (и более) раз медленнее, чем Aa, но для небольших массивов его можно использовать - для повышения ясности кода.

  • Циклы с длиной массива кешируются в n(Ab, Bb, Be) иногда быстрее, иногда нет. Вероятно, компиляторы автоматически обнаруживают эту ситуацию и вводят кеширование. Разница в скорости между кэшированной и не кэшированной версиями (Aa, Ba, Bd) составляет около 1%, поэтому похоже, чтоnэто микрооптимизация.

  • В i--например, решения, в которых цикл начинается с последнего элемента массива (Ac, Bc), обычно на ~30% медленнее, чем решения прямого действия - вероятно, причина в способе работы кеша памяти ЦП - чтение памяти вперед более оптимально для кэширования ЦП). Рекомендуется НЕ ИСПОЛЬЗОВАТЬ такие решения.

Детали

В тестах мы вычисляем сумму элементов массива. Я провожу тест для небольших массивов (10 элементов) и больших массивов (1M элементов) и делю их на три группы:

  • А -for тесты
  • B -while тесты
  • C - другие / альтернативные методы

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
//let arr = Array.from(Array(1000000), (x, i) => i%10);

function Aa(a, s=0) {
  for(let i=0; i<a.length; i++) {
    s += a[i];
  }
  console.log('Aa=', s);
}

function Ab(a, s=0) {
  let n = a.length;
  for(let i=0; i<n; i++) {
    s += a[i];
  }
  console.log('Ab=', s);
}

function Ac(a, s=0) {
  for(let i=a.length; i--;) {
    s += a[i];
  }
  console.log('Ac=', s);
}

function Ad(a, s=0) {
  for(let x of a) {
    s += x;
  }
  console.log('Ad=', s);
}

function Ae(a, s=0) {
  for(let i in a) if (a.hasOwnProperty(i)) {
    s += a[i];
  }
  console.log('Ae=', s);
}

function Ba(a, s=0) {
  let i = -1;
  while(++i < a.length) {
    s+= a[i];
  }
  console.log('Ba=', s);
}

function Bb(a, s=0) {
  let i = -1;
  let n = a.length;
  while(++i < n) {
    s+= a[i];
  }
  console.log('Bb=', s);
}

function Bc(a, s=0) {
  let i = a.length;
  while(i--) {
    s += a[i];
  }
  console.log('Bc=', s);
}

function Bd(a, s=0) {
  let i = 0;
  do {
    s+= a[i]
  } while (++i < a.length);
  console.log('Bd=', s);
}

function Be(a, s=0) {
  let i = 0;
  let n = a.length;
  do {
    s += a[i]
  } while (++i < n);
  console.log('Be=', s);
}

function Bf(a, s=0) {
  const it = a.values(); 
  let e;
  while (!(e = it.next()).done) { 
    s+= e.value; 
  }
  console.log('Bf=', s);
}

function Ca(a, s=0) {
  a.map(x => { s+=x });
  console.log('Ca=', s);
}

function Cb(a, s=0) {
  a.forEach(x => { s+=x });
  console.log('Cb=', s);
}

function Cc(a, s=0) {
  a.every(x => (s += x, 1));
  console.log('Cc=', s);
}

function Cd(a, s=0) {
  a.filter(x => { s+=x });
  console.log('Cd=',s);
}

function Ce(a, s=0) {
  a.reduce((z, c) => { s+=c }, 0);
  console.log('Ce=', s);
}

function Cf(a, s=0) {
  a.reduceRight((z, c) => { s += c }, 0);
  console.log('Cf=', s);
}

function Cg(a, s=0) {
  a.some(x => { s += x } );
  console.log('Cg=', s);
}

function Ch(a, s=0) {
  Array.from(a, x=> s += x);
  console.log('Cc=', s);
}


Aa(arr);
Ab(arr);
Ac(arr);
Ad(arr);
Ae(arr);

Ba(arr);
Bb(arr);
Bc(arr);
Bd(arr);
Be(arr);
Bf(arr);

Ca(arr);
Cb(arr);
Cc(arr);
Cd(arr);
Ce(arr);
Cf(arr);
Cg(arr);
Ch(arr);
<p style="color: red">This snippets only PRESENTS code used for benchmark - it not perform test itself</p>

Результаты кроссбраузерности

Результаты для всех протестированных браузеров

браузеры **

Массив из 10 элементов

Результаты для Chrome. Вы можете выполнить тест на вашей машине здесь.

Массив с 1000000 элементов

Результаты для Chrome. Вы можете выполнить тест на своей машине здесь

Резюме:

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

  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 возвращается как новый массив и оставляет старый массив нетронутым (за исключением случаев, когда вы манипулируете его простотой 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);

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

Перебирать элементы, используя for..of

for..of цикл проходит по каждому элементу массива (или любому другому итерируемому объекту). Это работает следующим образом:

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

for(let element of arr) {
  console.log(element * 2);
}

В приведенном выше примере element обозначает элемент массива и arr это массив, который мы хотим зациклить. Не то имя element является произвольным, и мы могли бы выбрать любое другое имя, например "el", или что-то более декларативное, когда это применимо.

Не путайте for..in цикл с for..of петля. for..in будет перебирать все перечисляемые свойства массива, тогда как for..of loop будет проходить только через элементы массива. Например:

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

arr.foo = 'foo';

for(let element of arr) {
  console.log(element);
}

for(let element in arr) {
  console.log(element);
}

Наиболее близким к вашей идее будет использование 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]

В соответствии с новой обновленной функцией ECMAScript 6 (ES6) и ECMAScript 2015 вы можете использовать следующие параметры с циклами:

для петель

for(var i = 0; i < 5; i++){
  console.log(i);
}

// Output: 0,1,2,3,4

for... в циклах

let obj = {"a":1, "b":2}

for(let k in obj){
  console.log(k)
}

// Output: a,b

Array.forEach()

let array = [1,2,3,4]

array.forEach((x) => {
  console.log(x);
})

// Output: 1,2,3,4

для... петель

let array = [1,2,3,4]

for(let x of array){
  console.log(x);
}

// Output: 1,2,3,4

пока петли

let x = 0

while(x < 5){
  console.log(x)
  x++
}

// Output: 1,2,3,4

делать... пока петли

let x = 0

do{
  console.log(x)
  x++
}while(x < 5)

// Output: 1,2,3,4

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

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

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

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

Лямбда-синтаксис обычно не работает в 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);
});

Если вы хотите перебрать массив объектов с помощью функции стрелки:

let arr=[{name:'john',age:50},{name:'clark',age:19},{name:'mohan',age:26}];

arr.forEach((person)=>{
  console.log('i am '+person.name+' and i am '+person.age+ ' old');
})

Другие вопросы по тегам