Я действительно искал это, но я искал forEach и не только for. как уже говорилось, в C # это было немного по-другому, и это меня смутило :)
Dante1986
6
ECMAScript & nbsp; 6 может содержать конструкцию «for ... of». Смотрите для ... of (MDN) для получения дополнительной информации. Вы уже можете попробовать это с последними версиями Firefox.
В отличие от этого , в Python является более эффективным , чтобы использовать функции , чем использование традиционных для петель. (Учтите , что i < lenи i++может быть сделано с помощью двигателя, а не переводчик.)
joeytwiddle
Ответы:
7023
TL; DR
Не используйте его, for-inесли не используете его с мерами предосторожности или, по крайней мере, не знаете, почему он может вас укусить.
Ваши лучшие ставки обычно
for-ofцикл (ES2015 + только),
Array#forEach( spec| MDN) (или его родственники someи тому подобное) (только ES5 +),
простая старомодная forпетля,
или for-inс гарантиями.
Но есть еще много интересного, читайте дальше ...
JavaScript имеет мощную семантику для циклического перемещения по массивам и объектам, похожим на массивы. Я разделил ответ на две части: параметры для подлинных массивов и параметры для объектов, похожих на массивы , таких как argumentsобъект, другие итерируемые объекты (ES2015 +), коллекции DOM и т. Д.
Я быстро отметить , что вы можете использовать ES2015 варианты в настоящее время , даже на двигателях ES5, по transpiling ES2015 в ES5. Искать "ES2015 transpiling" / "ES6 transpiling" для получения дополнительной информации ...
Хорошо, давайте посмотрим на наши варианты:
Для фактических массивов
У вас есть три варианта в ECMAScript 5 («ES5»), наиболее широко поддерживаемая на данный момент версия, и еще две, добавленные в ECMAScript 2015 («ES2015», «ES6»):
Использование forEachи связанные (ES5 +)
Используйте простой forцикл
Используйте for-inправильно
Использовать for-of(неявно использовать итератор) (ES2015 +)
Используйте итератор явно (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веб-страницу общего назначения без прокладки. Если вам требуется поддержка устаревших браузеров, forEachлегко выполнить shimming / polyfilling (найдите « 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]);}
Но с современными JavaScript-движками вам редко приходится вытаскивать последний кусок сока.
В ES2015 и выше вы можете сделать свои переменные индекса и значения локальными для forцикла:
let a =["a","b","c"];for(let index =0; index < a.length;++index){let value = a[index];
console.log(index, value);}//console.log(index); // would cause "ReferenceError: index is not defined"//console.log(value); // would cause "ReferenceError: value is not defined"
let a =["a","b","c"];for(let index =0; index < a.length;++index){let value = a[index];
console.log(index, value);}try{
console.log(index);}catch(e){
console.error(e);// "ReferenceError: index is not defined"}try{
console.log(value);}catch(e){
console.error(e);// "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 =>{
console.log("Index is: "+ index);});}
let divs = document.querySelectorAll("div");for(let index =0; index < divs.length;++index){
divs[index].addEventListener('click', e =>{
console.log("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будет следовать этому порядку; ES2020 сделал, хотя. (Подробности в этом другом ответе .)
Единственными реальными вариантами использования для for-inмассива являются:
Вы используете неэлементные свойства и хотите включить их в цикл
Рассмотрим только первый пример: вы можете использовать for-inэти редкие элементы массива, если используете соответствующие меры безопасности:
// `a` is a sparse arrayvar key;var a =[];
a[0]="a";
a[10]="b";
a[10000]="c";for(key in a){if(a.hasOwnProperty(key)&&// These checks are/^0$|^[1-9]\d*$/.test(key)&&// explained
key <=4294967294// below){
console.log(a[key]);}}
Что у объекта есть собственное свойство с таким именем (не то, которое он наследует от своего прототипа), и
Что ключом являются все десятичные цифры (например, обычная строковая форма, а не научная запись), и
Что значение ключа при наведении на число составляет <= 2 ^ 32 - 2 (что составляет 4 294 967 294). Откуда этот номер? Это часть определения индекса массива в спецификации . Другие числа (нецелые числа, отрицательные числа, числа больше 2 ^ 32 - 2) не являются индексами массива. Причина , это 2 ^ 32 - 2 такова, что делает наибольшее значение индекса один ниже , чем 2 ^ 32 - 1 , которое является максимальным значением массива - х lengthможет иметь. (Например, длина массива соответствует 32-разрядному целому числу без знака.) (Пропишет в RobG, указав в комментарии к моему сообщению в блоге, что мой предыдущий тест был не совсем правильным.)
Конечно, вы бы не сделали этого в встроенном коде. Вы бы написали служебную функцию. Может быть:
// Utility function for antiquated environments without `forEach`var hasOwn =Object.prototype.hasOwnProperty;var rexNum =/^0$|^[1-9]\d*$/;function sparseEach(array, callback, thisArg){var index;for(var key in array){
index =+key;if(hasOwn.call(a, key)&&
rexNum.test(key)&&
index <=4294967294){
callback.call(thisArg, array[key], index, array);}}}var a =[];
a[5]="five";
a[10]="ten";
a[100000]="one hundred thousand";
a.b ="bee";
sparseEach(a,function(value, index){
console.log("Value at "+ index +" is "+ value);});
Под прикрытием он получает итератор из массива и проходит по нему, получая значения из него. Это не имеет проблемы, которую for-inимеет использование с использованием , потому что он использует итератор, определенный объектом (массивом), и массивы определяют, что их итераторы выполняют итерацию через свои записи (не их свойства). В отличие от for-inES5, порядок посещения записей - это порядковый номер их индексов.
5. Используйте итератор явно (ES2015 +)
Иногда вам может понадобиться явно использовать итератор . Вы тоже можете это сделать, хотя это намного более неприятно, чем . Это выглядит так:for-of
const a =["a","b","c"];const it = a.values();let 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объект и т. Д. Как мы перебираем их содержимое?
Используйте любой из параметров выше для массивов
По крайней мере, некоторые, и, возможно, большинство или даже все вышеописанные подходы к массивам часто одинаково хорошо применимы к объектам, подобным массивам:
Использование 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`});
Используйте простой forцикл
Очевидно, что простой forцикл применяется к объектам, подобным массиву.
Используйте for-inправильно
for-inс теми же средствами защиты, что и с массивом, должны работать и с объектами, подобными массиву; может применяться предостережение для предоставленных хостом объектов на # 1 выше.
Использовать for-of(неявно использовать итератор) (ES2015 +)
for-ofиспользует итератор, предоставленный объектом (если есть). Это включает предоставленные хостом объекты. Например, спецификация для NodeListfrom querySelectorAllбыла обновлена для поддержки итерации. Спец для HTMLCollectionот getElementsByTagNameне было.
Используйте итератор явно (ES2015 +)
Смотрите № 4.
Создать истинный массив
В других случаях вы можете захотеть преобразовать подобный массиву объект в истинный массив. Делать это на удивление легко:
Используйте sliceметод массивов
Мы можем использовать sliceметод массивов, который, как и другие методы, упомянутые выше, является «преднамеренно родовым» и поэтому может использоваться с объектами, похожими на массивы, например так:
var trueArray =Array.prototype.slice.call(arrayLikeObject);
Так, например, если мы хотим преобразовать a NodeListв истинный массив, мы могли бы сделать это:
var divs =Array.prototype.slice.call(document.querySelectorAll("div"));
Смотрите Caveat для предоставленных хостом объектов ниже. В частности, обратите внимание, что это не удастся в IE8 и более ранних версиях, которые не позволяют вам использовать предоставленные хостом объекты, как thisэто.
Использовать распространенный синтаксис ( ...)
Также возможно использовать синтаксис распространения ES2015 с механизмами JavaScript, которые поддерживают эту функцию. Например for-of, здесь используется итератор, предоставленный объектом (см. # 4 в предыдущем разделе):
var trueArray =[...iterableObject];
Так, например, если мы хотим преобразовать a NodeListв истинный массив, с распространенным синтаксисом это становится довольно кратким:
var divs =[...document.querySelectorAll("div")];
использование Array.from
Array.from(спец) | (MDN) (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]]всегда генерируется значение false .
(Я не мог найти эквивалентную формулировку в ES2015 спецификации, но это связано , по - прежнему имеет место.) Опять же , как и на момент написания этого общего хоста предоставляется массив типа объектов в современных браузерах [ NodeListслучаях, например] сделать ручку [[HasProperty]]правильно, но важно проверить.)
Я также хотел бы добавить, что .forEachэто не может быть эффективно сломано. Вы должны бросить исключение, чтобы выполнить перерыв.
Пиюсн
82
@Pius: Если вы хотите разорвать цикл, вы можете использовать some. (Я бы предпочел также разрешить взлом forEach, но они меня не спрашивали. ;-))
TJ Crowder
6
@TJCrowder Правда, хотя это выглядит скорее как обходной путь, поскольку это не его основная цель.
Пиюсн
8
@ user889030: Вам нужно ,после k=0, а не ;. Помните, программирование - это много вещей, одним из которых является пристальное внимание к деталям ... :-)
TJ Crowder
5
@JimB: это описано выше (и lengthэто не метод). :-)
TJ Crowder
513
Примечание . Этот ответ безнадежно устарел. Для более современного подхода посмотрите на методы, доступные в массиве . Интересующие методы могут быть:
для каждого
карта
фильтр
застежка-молния
уменьшить
каждый
несколько
Стандартный способ итерации массива в JavaScript - это vanilla 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, но он не поддерживается в устаревших браузерах. Поэтому, чтобы иметь возможность использовать его последовательно, вы должны либо иметь среду, которая его поддерживает (например, Node.js для серверного JavaScript), либо использовать «Polyfill». Polyfill для этой функциональности, однако, тривиален, и, поскольку он делает код более легким для чтения, его стоит включить в Polyfill.
почему for(instance in objArray) не правильное использование? это выглядит более простым для меня, но я слышал, вы говорите об этом как о неправильном способе использования?
Dante1986
21
Вы можете использовать встроенное кэширование длины: for (var i = 0, l = arr.length; i <l; i ++)
Robert Hoffmann
3
Запятая в конце первой строки является преднамеренной, или это опечатка (может быть точка с запятой)?
Мохд Абдул Муджиб
6
@ wardha-Web Это намеренно. Это позволяет нам объявлять несколько переменных одним varключевым словом. Если бы мы использовали точку с запятой, то elementбыли бы объявлены в глобальной области (или, скорее, JSHint кричал бы на нас, прежде чем он достигнет производства).
PatrikAkerstrand
239
Если вы используете библиотеку 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].}
Я, вероятно, собираюсь использовать этот ответ чаще всего. Это не лучший ответ на вопрос, но на практике он будет самым простым и наиболее применимым для тех из нас, кто использует jQuery. Я думаю, что мы все должны учиться ванили тоже. Это никогда не повредит расширению вашего понимания.
mopsyd
47
Просто ради этого: каждый jQuery намного медленнее, чем нативные решения. JQuery рекомендует использовать нативный JavaScript вместо jQuery, когда это возможно. jsperf.com/browser-diet-jquery-each-vs-for-loop
Кевин Босс,
8
Воздержитесь от использования jQuery, когда вы можете использовать vanilla js
Noe
2
Придерживайтесь стандартного JS, держите сторонние библиотеки вне ответа, если нет решения на родном языке
scubasteve
116
Петля назад
Я думаю, что обратный цикл заслуживает упоминания здесь:
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..of). Причины, чтобы отдать предпочтение forEachперед обратным циклом:
Это яснее читать.
Это указывает на то, что я не собираюсь сдвигаться в блоке (что всегда является возможным сюрпризом, скрывающимся в длинных forи whileпетлях).
Это дает вам свободную возможность для закрытия.
Это уменьшает утечку локальных переменных и случайное столкновение с (и мутацией) внешних переменных.
Затем, когда вы видите обратный цикл for в своем коде, это намек на то, что он полностью изменен (возможно, это одна из причин, описанных выше). И видение традиционного цикла for for может указывать на то, что сдвиг может иметь место.
(Если обсуждение намерений не имеет смысла для вас, тогда вы и ваш код можете получить пользу от просмотра лекции Крокфорда « Стиль программирования и ваш мозг» .)
Теперь еще лучше использовать для ... из!
Существует дискуссия о том , for..ofили forEach()предпочтительнее:
Для максимальной поддержки браузера for..ofтребуется многократное заполнение для итераторов, что делает ваше приложение немного медленнее для выполнения и немного больше для загрузки.
Лично я склонен использовать все, что выглядит проще для чтения, если только производительность или минимизация не стали серьезной проблемой. Поэтому в эти дни я предпочитаю использовать for..ofвместо forEach(), но я всегда буду использовать mapили filterили findили someкогда это применимо. (Ради своих коллег я редко пользуюсь reduce.)
Как это работает?
for(var i =0; i < array.length; i++){...}// Forwardsfor(var i = array.length; i--;){...}// Reverse
Вы заметите, что i--это среднее предложение (где мы обычно видим сравнение), а последнее предложение пустое (где мы обычно видим i++). Это означает, что i--также используется как условие для продолжения. Важно, что он выполняется и проверяется перед каждой итерацией.
Как это может начаться array.lengthбез взрыва?
Поскольку i--выполняется перед каждой итерацией, на первой итерации мы фактически получим доступ к элементу, array.length - 1что позволяет избежать любых проблем с элементами Array-out-of-boundsundefined .
Почему он не прекращает итерации до индекса 0?
Цикл прекратит итерацию, когда условие i--оценивается как ложное значение (когда оно возвращает 0).
Хитрость в том, что в отличие --iот конечного i--оператора декремент уменьшается, iно выдает значение перед декрементом. Ваша консоль может продемонстрировать это:
> var i = 5; [i, i--, i];
[5, 5, 4]
Таким образом, на последней итерации я был ранее равен 1, и i--выражение меняет его на 0, но на самом деле возвращает 1 (правда), и поэтому условие выполняется. На следующей итерации значение ii-- изменяется на -1, но возвращается 0 (фальси), в результате чего выполнение немедленно выпадает из нижней части цикла.
В традиционных вперед для цикла, i++и ++iявляются взаимозаменяемыми (как Дуглас Крокфорд указывает). Однако в обратном цикле for, поскольку наш декремент также является условным выражением, мы должны придерживаться его, i--если хотим обработать элемент с индексом 0.
пустяки
Некоторые люди любят рисовать маленькую стрелку в обратном forцикле и заканчивают миганием:
for(var i = array.length; i -->0;){
Кредиты идут в WYL для того, чтобы показать мне преимущества и ужасы обратного цикла.
Я забыл добавить тесты . Я также забыл упомянуть, что обратная петля является значительной оптимизацией для 8-разрядных процессоров, таких как 6502, где вы действительно получаете сравнение бесплатно!
Joeytwiddle
Тот же ответ дается гораздо более кратко здесь (на другой вопрос).
Joeytwiddle
84
Некоторые языки 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 находится в документации, поэтому вы все равно можете использовать его для старых браузеров):
Важно отметить, что Array.prototype.forEachон не прерывается, когда возвращается обратный вызов false. jQuery и Underscore.js предоставляют свои собственные варианты eachдля обеспечения циклов, которые могут быть закорочены.
Итак, как же вырваться из цикла foreach ECMAScript5, как мы это сделали бы для цикла for for или цикла foreach, подобного тому, который есть в языках стиля C?
Кьяран Галлахер
5
@CiaranG, в JavaScript часто встречаются eachметоды, позволяющие return falseиспользовать их для выхода из цикла, но forEachэто не вариант. Можно использовать внешний флаг (т . if (flag) return;forEach
Е.
43
Если вы хотите зациклить массив, используйте стандартный forцикл из трех частей .
for(var i =0; i < myArray.length; i++){var arrayItem = myArray[i];}
Вы можете добиться некоторой оптимизации производительности, кэшируя myArray.lengthили перебирая ее в обратном порядке.
потому что (var i = 0, length = myArray.length; i <length; i ++) должны это сделать
Эдсон Медина,
5
@EdsonMedina Это также создаст новую глобальную переменную с именем length. ;)
joeytwiddle
4
@joeytwiddle Да, но это выходит за рамки этого поста. Вы все равно создадите глобальную переменную.
Эдсон Медина
6
@EdsonMedina Мои извинения, я ошибся. Использование ,после назначения не вводит новый глобальный, так что ваше предложение просто отлично ! Я путал это с другой проблемой: использование =после присваивания создает новый глобал.
Joeytwiddle
Остерегайтесь, переменная i не является локальной для цикла. У JavaScript нет блочной области видимости. Вероятно, лучше объявить var i, length, arrayItem;перед циклом, чтобы избежать этого недоразумения.
Джеймс
35
Я знаю, что это старый пост, и уже есть так много хороших ответов. Для большей полноты я решил добавить еще один, используя 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функции в отличие от встроенного 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 loopfor(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этого плохого парня.
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});
Вероятно, for(i = 0; i < array.length; i++)петля не лучший выбор. Почему? Если у вас есть это:
var array =newArray();
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в 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
Где ofизбегает странностей, связанных с inи заставляет его работать как forцикл любого другого языка, и letсвязывается iвнутри цикла, а не внутри функции.
Скобки ( {}) могут быть опущены, когда есть только одна команда (например, в примере выше).
Простым решением сейчас будет использование библиотеки underscore.js . Он предоставляет много полезных инструментов, таких как eachи автоматически делегирует работу нативной, forEachесли она доступна.
Там нет никакого for eachцикла в нативном JavaScript . Вы можете использовать библиотеки, чтобы получить эту функциональность (я рекомендую Underscore.js ), используйте простой forцикл.
Это итератор для не разреженного списка, где индекс начинается с 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 );returnthis;}Array.prototype.each = each;
Примеры использования:
Пример № 1
var arr =[];[1,2,3].each(function(a){ a.push(this*this}, arr);
arr =[1,4,9]
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-тегов заменены на зеленые.
Предостережение при использовании строки в качестве функции: функция создается вне контекста и должна использоваться только в том случае, если вы уверены в области видимости переменной. В противном случае лучше передавать функции там, где обзор более интуитивно понятен.
Есть несколько способов перебрать массив в 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;
Функциональные циклы - forEach, map, filter, и reduce(они перебрать функции, но они используются , если вам нужно что - то делать с вашим массивом и т.д.
// For example, in this case we loop through the number and double them up using the map functionvar numbers =[65,44,12,4];
document.getElementById("example").innerHTML = numbers.map(function(num){return num *2});
Небольшое исправление: forEachэто не «функциональный» цикл, поскольку он не возвращает новый Array(на самом деле он ничего не возвращает), он просто повторяется.
nicholaswmin
19
ECMAScript 5 (версия на JavaScript) для работы с массивами:
forEach - выполняет итерацию по каждому элементу в массиве и делает с каждым элементом все, что вам нужно.
['C','D','E'].forEach(function(element, index){
console.log(element +" is #"+(index+1)+" in the 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']
уменьшить - как следует из названия, он сводит массив к одному значению, вызывая данную функцию, передавая текущий элемент и результат предыдущего выполнения.
Там нет встроенной способности взломать 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 (неопределенный и т. Д.). Это может быть использовано как преимущество, хотя. Тем не менее, это будет немного сложнее для чтения. А также, в зависимости от браузера, его можно «не» оптимизировать, чтобы он работал быстрее оригинального.
Разрушение и использование оператора распространения оказалось весьма полезным для новичков в ECMAScript 6 как более удобочитаемый / эстетичный, хотя некоторые ветераны JavaScript могут посчитать это грязным. Юниоры или другие люди могут найти это полезным.
В следующих примерах будут использоваться for...ofоператор и .forEachметод.
Примеры 6, 7 и 8 могут быть использованы с какими - либо функциональными петлями , такими как .map, .filter, .reduce, .sort, .every, .some. Для получения дополнительной информации об этих методах, проверьте Array Object .
Пример 1: Обычный for...ofцикл - здесь никаких хитростей.
let arrSimple =['a','b','c'];for(let letter of arrSimple){
console.log(letter);}
let arrFruits =['apple','orange','banana'];for(let[firstLetter,...restOfTheWord]of arrFruits){// Create a shallow copy using the spread operatorlet[lastLetter]=[...restOfTheWord].reverse();
console.log(firstLetter, lastLetter, restOfTheWord);}
// 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);}
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);});
let arrWithObjects =[{
name:'Jon',
age:32},{
name:'Elise',
age:33}];// NOTE: Destructuring objects while using shorthand functions// are required to be surrounded by parentheses
arrWithObjects.forEach(({ name, age: aliasForAge })=>{
console.log(name, aliasForAge)});
Самый близкий к вашей идее способ - использовать Array.forEach()функцию закрытия, которая будет выполняться для каждого элемента массива.
myArray.forEach((item)=>{// Do something
console.log(item);});
Другим жизнеспособным способом было бы использовать Array.map()метод, который работает таким же образом, но он также принимает все возвращаемые значения и возвращает их в новом массиве (по существу, отображая каждый элемент в новый), например так:
Это неправильно, mapне изменяет элементы массива, поскольку возвращает новый массив, а элементы этого нового являются результатом применения функции к элементам старого массива.
Хесус Франко
Я никогда не говорил, что он не возвращает новый массив, я имел в виду изменение, примененное функцией. Но здесь я изменю это в ответе.
Анте Яблан Адамович
опять же неправильно, карта не изменяет и не изменяет все элементы в исходном массиве, я предложил и отредактирую ответ, подчеркнув, что карта работает с копией оригинальных элементов, оставив исходный массив без изменений
Jesús Franco
7
Вы можете позвонить forEach, как это:
forEachбудет выполнять итерацию по предоставленному вами массиву, и для каждой итерации будет иметь elementзначение этой итерации. Если вам нужен индекс, вы можете получить текущий индекс, передав в iкачестве второго параметра функцию обратного вызова для forEach.
Foreach - это в основном функция высокого порядка, которая принимает в качестве параметра другую функцию.
let theArray=[1,3,2];
theArray.forEach((element)=>{// Use the element of the array
console.log(element)}
Вывод:
132
Вы также можете перебрать массив так:
for(let i=0; i<theArray.length; i++){
console.log(i);// i will have the value of each 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');})
Лямбда-синтаксис обычно не работает в Internet Explorer 10 или ниже.
Я обычно использую
[].forEach.call(arrayName,function(value,index){
console.log("value of the looped element"+ value);
console.log("index of the looped element"+ index);});
Если вы являетесь поклонником jQuery и у вас уже запущен файл jQuery, вам следует поменять местами позиции индекса и значения параметров
$("#ul>li").each(function(**index, value**){
console.log("value of the looped element"+ value);
console.log("index of the looped element"+ index);});
Если у вас есть массивный массив, вы должны использовать, iteratorsчтобы получить некоторую эффективность. Итераторы свойство некоторых коллекций JavaScript (как Map, Set, String, Array). Даже for..ofиспользует iteratorпод капотом.
Итераторы повышают эффективность, позволяя вам использовать элементы списка по одному, как если бы они были потоком. Что делает итератор особенным, так это то, как он пересекает коллекцию. Другие циклы должны загружать всю коллекцию заранее, чтобы выполнить итерацию, тогда как итератору нужно знать только текущую позицию в коллекции.
Вы получаете доступ к текущему элементу, вызывая метод итератора next. Следующий метод вернет valueтекущий элемент и a, 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());
Сегодня (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 элементов) и делю их на три группы:
При переборе массива мы часто хотим выполнить одну из следующих целей:
Мы хотим перебрать массив и создать новый массив:
Array.prototype.map
Мы хотим перебрать массив и не создавать новый массив:
Array.prototype.forEach
for..ofпетля
В JavaScript есть много способов достижения обеих этих целей. Однако некоторые из них более удобны, чем другие. Ниже вы можете найти некоторые часто используемые методы (наиболее удобный 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Петли петли через каждый элемент массива (или любого другого объекта Iterable). Это работает следующим образом:
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цикл будет проходить только через элементы массива. Например:
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);}
forEach
и не толькоfor
. как уже говорилось, в C # это было немного по-другому, и это меня смутило :)i < len
иi++
может быть сделано с помощью двигателя, а не переводчик.)Ответы:
TL; DR
for-in
если не используете его с мерами предосторожности или, по крайней мере, не знаете, почему он может вас укусить.Ваши лучшие ставки обычно
for-of
цикл (ES2015 + только),Array#forEach
(spec
|MDN
) (или его родственникиsome
и тому подобное) (только ES5 +),for
петля,for-in
с гарантиями.Но есть еще много интересного, читайте дальше ...
JavaScript имеет мощную семантику для циклического перемещения по массивам и объектам, похожим на массивы. Я разделил ответ на две части: параметры для подлинных массивов и параметры для объектов, похожих на массивы , таких как
arguments
объект, другие итерируемые объекты (ES2015 +), коллекции DOM и т. Д.Я быстро отметить , что вы можете использовать ES2015 варианты в настоящее время , даже на двигателях ES5, по transpiling ES2015 в ES5. Искать "ES2015 transpiling" / "ES6 transpiling" для получения дополнительной информации ...
Хорошо, давайте посмотрим на наши варианты:
Для фактических массивов
У вас есть три варианта в ECMAScript 5 («ES5»), наиболее широко поддерживаемая на данный момент версия, и еще две, добавленные в ECMAScript 2015 («ES2015», «ES6»):
forEach
и связанные (ES5 +)for
циклfor-in
правильноfor-of
(неявно использовать итератор) (ES2015 +)Подробности:
1. Использование
forEach
и связанныеВ любой неопределенно современной среде (например, не в IE8), где у вас есть доступ к
Array
функциям, добавленным ES5 (напрямую или с использованием полифиллов), вы можете использоватьforEach
(spec
|MDN
):forEach
принимает функцию обратного вызова и, необязательно, значение для использования, какthis
при вызове этого обратного вызова (не используется выше). Обратный вызов вызывается для каждой записи в массиве, чтобы пропустить несуществующие записи в разреженных массивах. Хотя выше я использовал только один аргумент, обратный вызов вызывается с тремя: значением каждой записи, индексом этой записи и ссылкой на массив, по которому вы перебираете (в случае, если ваша функция еще не имеет этого под рукой) ).Если вы не поддерживаете устаревшие браузеры, такие как IE8 (на долю которого NetApps приходится чуть более 4% рынка на момент написания этой статьи в сентябре 2016 года), вы можете без проблем использовать
forEach
веб-страницу общего назначения без прокладки. Если вам требуется поддержка устаревших браузеров,forEach
легко выполнить shimming / polyfilling (найдите « es5 shim » для нескольких вариантов).forEach
Преимущество заключается в том, что вам не нужно объявлять переменные индексации и значений в содержащей области, так как они передаются в качестве аргументов функции итерации и так хорошо подходят только для этой итерации.Если вас беспокоит стоимость выполнения вызова функции для каждой записи массива, не беспокойтесь; подробности .
Кроме того,
forEach
есть функция «проходить через них все», но ES5 определила несколько других полезных функций «прорабатывать массив и делать вещи», включая:every
(перестает зацикливаться в первый раз, когда возвращается обратный вызовfalse
или что-то не так)some
(перестает зацикливаться при первом возвратеtrue
или обратном вызове)filter
(создает новый массив, включающий элементы, в которые возвращает функция фильтра,true
и пропускает те, в которых она возвращаетсяfalse
)map
(создает новый массив из значений, возвращаемых обратным вызовом)reduce
(создает значение путем многократного вызова обратного вызова, передавая предыдущие значения; подробности см. в спецификации; полезно для суммирования содержимого массива и многих других)reduceRight
(нравитсяreduce
, но работает в порядке убывания, а не в порядке возрастания)2. Используйте простой
for
циклИногда старые способы являются лучшими:
Если длина массива не будет меняться в течение цикла, и это в исполнении чувствительной коды (маловероятно), чуть более сложный вариант захвата длиной фронта может быть крошечными немного быстрее:
И / или считая в обратном направлении:
Но с современными JavaScript-движками вам редко приходится вытаскивать последний кусок сока.
В ES2015 и выше вы можете сделать свои переменные индекса и значения локальными для
for
цикла:Показать фрагмент кода
И когда вы делаете это, не только,
value
но иindex
воссоздается для каждой итерации цикла, то есть замыкания, созданные в теле цикла, сохраняют ссылку наindex
(иvalue
), созданный для этой конкретной итерации:Показать фрагмент кода
Если бы у вас было пять делений, вы получили бы «Индекс: 0», если вы щелкнули по первому, и «Индекс: 4», если вы щелкнули по последнему. Это не работает, если вы используете
var
вместоlet
.3. Используйте
for-in
правильноВы получите людей, говорящих вам, чтобы использовать
for-in
, но это не тоfor-in
, для чего .for-in
циклически перебирает перечисляемые свойства объекта , а не индексы массива. Заказ не гарантирован , даже в ES2015 (ES6). ES2015 + действительно определяет порядок свойств объекта (через[[OwnPropertyKeys]]
,[[Enumerate]]
и вещи, которые используют их какObject.getOwnPropertyKeys
), но он не определил, чтоfor-in
будет следовать этому порядку; ES2020 сделал, хотя. (Подробности в этом другом ответе .)Единственными реальными вариантами использования для
for-in
массива являются:Рассмотрим только первый пример: вы можете использовать
for-in
эти редкие элементы массива, если используете соответствующие меры безопасности:Обратите внимание на три проверки:
Что у объекта есть собственное свойство с таким именем (не то, которое он наследует от своего прототипа), и
Что ключом являются все десятичные цифры (например, обычная строковая форма, а не научная запись), и
Что значение ключа при наведении на число составляет <= 2 ^ 32 - 2 (что составляет 4 294 967 294). Откуда этот номер? Это часть определения индекса массива в спецификации . Другие числа (нецелые числа, отрицательные числа, числа больше 2 ^ 32 - 2) не являются индексами массива. Причина , это 2 ^ 32 - 2 такова, что делает наибольшее значение индекса один ниже , чем 2 ^ 32 - 1 , которое является максимальным значением массива - х
length
может иметь. (Например, длина массива соответствует 32-разрядному целому числу без знака.) (Пропишет в RobG, указав в комментарии к моему сообщению в блоге, что мой предыдущий тест был не совсем правильным.)Конечно, вы бы не сделали этого в встроенном коде. Вы бы написали служебную функцию. Может быть:
Показать фрагмент кода
4. Используйте
for-of
(неявно используйте итератор) (ES2015 +)ES2015 добавил итераторы в JavaScript. Самый простой способ использовать итераторы - это новый
for-of
оператор. Это выглядит так:Под прикрытием он получает итератор из массива и проходит по нему, получая значения из него. Это не имеет проблемы, которую
for-in
имеет использование с использованием , потому что он использует итератор, определенный объектом (массивом), и массивы определяют, что их итераторы выполняют итерацию через свои записи (не их свойства). В отличие отfor-in
ES5, порядок посещения записей - это порядковый номер их индексов.5. Используйте итератор явно (ES2015 +)
Иногда вам может понадобиться явно использовать итератор . Вы тоже можете это сделать, хотя это намного более неприятно, чем . Это выглядит так:
for-of
Итератор - это объект, соответствующий определению Итератора в спецификации. Его
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
объект и т. Д. Как мы перебираем их содержимое?Используйте любой из параметров выше для массивов
По крайней мере, некоторые, и, возможно, большинство или даже все вышеописанные подходы к массивам часто одинаково хорошо применимы к объектам, подобным массивам:
Использование
forEach
и связанные (ES5 +)Различные функции
Array.prototype
являются «преднамеренно общими» и обычно могут использоваться в объектах, подобных массивам, черезFunction#call
илиFunction#apply
. (См. Caveat для предоставленных хостом объектов в конце этого ответа, но это редкая проблема.)Предположим , вы хотите использовать
forEach
на множестве АNode
«SchildNodes
собственности. Вы бы сделали это:Если вы собираетесь делать это много, вы можете скопировать ссылку на функцию в переменную для повторного использования, например:
Используйте простой
for
циклОчевидно, что простой
for
цикл применяется к объектам, подобным массиву.Используйте
for-in
правильноfor-in
с теми же средствами защиты, что и с массивом, должны работать и с объектами, подобными массиву; может применяться предостережение для предоставленных хостом объектов на # 1 выше.Использовать
for-of
(неявно использовать итератор) (ES2015 +)for-of
использует итератор, предоставленный объектом (если есть). Это включает предоставленные хостом объекты. Например, спецификация дляNodeList
fromquerySelectorAll
была обновлена для поддержки итерации. Спец дляHTMLCollection
отgetElementsByTagName
не было.Используйте итератор явно (ES2015 +)
Смотрите № 4.
Создать истинный массив
В других случаях вы можете захотеть преобразовать подобный массиву объект в истинный массив. Делать это на удивление легко:
Используйте
slice
метод массивовМы можем использовать
slice
метод массивов, который, как и другие методы, упомянутые выше, является «преднамеренно родовым» и поэтому может использоваться с объектами, похожими на массивы, например так:Так, например, если мы хотим преобразовать a
NodeList
в истинный массив, мы могли бы сделать это:Смотрите Caveat для предоставленных хостом объектов ниже. В частности, обратите внимание, что это не удастся в IE8 и более ранних версиях, которые не позволяют вам использовать предоставленные хостом объекты, как
this
это.Использовать распространенный синтаксис (
...
)Также возможно использовать синтаксис распространения ES2015 с механизмами JavaScript, которые поддерживают эту функцию. Например
for-of
, здесь используется итератор, предоставленный объектом (см. # 4 в предыдущем разделе):Так, например, если мы хотим преобразовать a
NodeList
в истинный массив, с распространенным синтаксисом это становится довольно кратким:использование
Array.from
Array.from
(спец) | (MDN) (ES2015 +, но легко заполняемый) создает массив из объекта, подобного массиву, при необходимости сначала пропуская записи через функцию отображения. Так:Или, если вы хотите получить массив имен тегов элементов с данным классом, вы бы использовали функцию отображения:
Предостережение для предоставленных хостом объектов
Если вы используете
Array.prototype
функции с предоставленными хостом массивоподобными объектами (списки DOM и другие вещи, предоставляемые браузером, а не механизмом JavaScript), вам нужно обязательно протестировать в своих целевых средах, чтобы убедиться, что предоставленный хостом объект ведет себя правильно , Большинство ведут себя правильно (сейчас), но важно проверить. Причина в том, что большинствоArray.prototype
методов, которые вы, вероятно, захотите использовать, полагаются на предоставленный хостом объект, дающий честный ответ на абстрактную[[HasProperty]]
операцию. На момент написания статьи браузеры отлично справлялись с этой задачей, но спецификация 5.1 действительно допускала вероятность того, что предоставленный хостом объект может быть не честным. Это в §8.6.2 , несколько параграфов ниже большой таблицы в начале этого раздела), где написано:(Я не мог найти эквивалентную формулировку в ES2015 спецификации, но это связано , по - прежнему имеет место.) Опять же , как и на момент написания этого общего хоста предоставляется массив типа объектов в современных браузерах [
NodeList
случаях, например] сделать ручку[[HasProperty]]
правильно, но важно проверить.)источник
.forEach
это не может быть эффективно сломано. Вы должны бросить исключение, чтобы выполнить перерыв.some
. (Я бы предпочел также разрешить взломforEach
, но они меня не спрашивали. ;-)),
послеk=0
, а не;
. Помните, программирование - это много вещей, одним из которых является пристальное внимание к деталям ... :-)length
это не метод). :-)Примечание . Этот ответ безнадежно устарел. Для более современного подхода посмотрите на методы, доступные в массиве . Интересующие методы могут быть:
Стандартный способ итерации массива в JavaScript - это vanilla
for
-loop:Обратите внимание, однако, что этот подход хорош, только если у вас есть плотный массив, и каждый индекс занят элементом. Если массив разреженный, то при таком подходе вы можете столкнуться с проблемами производительности, так как вы будете перебирать множество индексов, которых на самом деле нет в массиве. В этом случае
for .. in
лучше использовать -loop. Однако вы должны использовать соответствующие меры предосторожности, чтобы гарантировать, что только требуемые свойства массива (то есть элементы массива) будут применены, так какfor..in
-loop будет также перечисляться в устаревших браузерах, или если дополнительные свойства определены какenumerable
,В ECMAScript 5 для прототипа массива будет использоваться метод forEach, но он не поддерживается в устаревших браузерах. Поэтому, чтобы иметь возможность использовать его последовательно, вы должны либо иметь среду, которая его поддерживает (например, Node.js для серверного JavaScript), либо использовать «Polyfill». Polyfill для этой функциональности, однако, тривиален, и, поскольку он делает код более легким для чтения, его стоит включить в Polyfill.
источник
for(instance in objArray)
не правильное использование? это выглядит более простым для меня, но я слышал, вы говорите об этом как о неправильном способе использования?var
ключевым словом. Если бы мы использовали точку с запятой, тоelement
были бы объявлены в глобальной области (или, скорее, JSHint кричал бы на нас, прежде чем он достигнет производства).Если вы используете библиотеку jQuery , вы можете использовать jQuery.each :
РЕДАКТИРОВАТЬ :
Что касается вопроса, пользователь хочет код в javascript вместо jquery, поэтому редактирование
источник
Петля назад
Я думаю, что обратный цикл заслуживает упоминания здесь:
Преимущества:
len
переменную или сравниватьarray.length
на каждой итерации, что может быть минутной оптимизацией.array[i]
), тогда цикл в прямом направлении пропускает элемент, сдвинутый влево в положение i , или повторно обрабатывает i- й элемент, который был смещено вправо. В традиционном цикле for вы можете обновить i, чтобы он указывал на следующий элемент, который нуждается в обработке - 1, но простое изменение направления итерации часто является более простым и элегантным решением .forEach()
ES6for ... of
.Недостатки:
Я должен всегда использовать это?
Некоторые разработчики по умолчанию используют обратный цикл for , если нет веских причин для циклического продвижения вперед.
Хотя прирост производительности обычно незначителен, это своего рода крики:
Однако на практике , что это не на самом деле является надежным показателем намерения, поскольку она ничем не отличается от тех случаев , когда вы делаете заботиться о порядке, и действительно необходимо , чтобы петли в обратном. Так что на самом деле для точного выражения намерения «все равно» потребуется другая конструкция, которая в настоящее время недоступна в большинстве языков, включая ECMAScript, но которую можно вызвать, например
forEachUnordered()
,.Если порядок не имеет значения, и эффективность является проблемой (в самом внутреннем цикле игрового или анимационного движка), тогда может быть приемлемым использовать цикл for в качестве обратного шаблона. Просто помните, что просмотр обратного цикла for в существующем коде не обязательно означает, что порядок не имеет значения!
Лучше было использовать forEach ()
В целом для кода более высокого уровня, где ясность и безопасность важнее, я ранее рекомендовал использовать в
Array::forEach
качестве шаблона по умолчанию для циклов (хотя в эти дни я предпочитаю использоватьfor..of
). Причины, чтобы отдать предпочтениеforEach
перед обратным циклом:for
иwhile
петлях).Затем, когда вы видите обратный цикл for в своем коде, это намек на то, что он полностью изменен (возможно, это одна из причин, описанных выше). И видение традиционного цикла for for может указывать на то, что сдвиг может иметь место.
(Если обсуждение намерений не имеет смысла для вас, тогда вы и ваш код можете получить пользу от просмотра лекции Крокфорда « Стиль программирования и ваш мозг» .)
Теперь еще лучше использовать для ... из!
Существует дискуссия о том ,
for..of
илиforEach()
предпочтительнее:Для максимальной поддержки браузера
for..of
требуется многократное заполнение для итераторов, что делает ваше приложение немного медленнее для выполнения и немного больше для загрузки.По этой причине (и для поощрения использования
map
иfilter
), некоторые руководства по стилю интерфейсаfor..of
полностью запрещены !Но вышеперечисленные проблемы не применимы к приложениям Node.js, где
for..of
теперь хорошо поддерживается.И тем более
await
не работает внутриforEach()
. Использованиеfor..of
- самый ясный образец в этом случае.Лично я склонен использовать все, что выглядит проще для чтения, если только производительность или минимизация не стали серьезной проблемой. Поэтому в эти дни я предпочитаю использовать
for..of
вместоforEach()
, но я всегда буду использоватьmap
илиfilter
илиfind
илиsome
когда это применимо. (Ради своих коллег я редко пользуюсьreduce
.)Как это работает?
Вы заметите, что
i--
это среднее предложение (где мы обычно видим сравнение), а последнее предложение пустое (где мы обычно видимi++
). Это означает, чтоi--
также используется как условие для продолжения. Важно, что он выполняется и проверяется перед каждой итерацией.Как это может начаться
array.length
без взрыва?Поскольку
i--
выполняется перед каждой итерацией, на первой итерации мы фактически получим доступ к элементу,array.length - 1
что позволяет избежать любых проблем с элементамиArray-out-of-boundsundefined
.Почему он не прекращает итерации до индекса 0?
Цикл прекратит итерацию, когда условие
i--
оценивается как ложное значение (когда оно возвращает 0).Хитрость в том, что в отличие
--i
от конечногоi--
оператора декремент уменьшается,i
но выдает значение перед декрементом. Ваша консоль может продемонстрировать это:> var i = 5; [i, i--, i];
[5, 5, 4]
Таким образом, на последней итерации я был ранее равен 1, и
i--
выражение меняет его на 0, но на самом деле возвращает 1 (правда), и поэтому условие выполняется. На следующей итерации значение ii--
изменяется на -1, но возвращается 0 (фальси), в результате чего выполнение немедленно выпадает из нижней части цикла.В традиционных вперед для цикла,
i++
и++i
являются взаимозаменяемыми (как Дуглас Крокфорд указывает). Однако в обратном цикле for, поскольку наш декремент также является условным выражением, мы должны придерживаться его,i--
если хотим обработать элемент с индексом 0.пустяки
Некоторые люди любят рисовать маленькую стрелку в обратном
for
цикле и заканчивают миганием:Кредиты идут в WYL для того, чтобы показать мне преимущества и ужасы обратного цикла.
источник
Некоторые языки C- стиля используют
foreach
для циклического перебора перечислений. В JavaScript это делается с помощьюfor..in
структуры цикла :Есть подвох.
for..in
будет проходить через каждый из перечисляемых членов объекта и членов его прототипа. Чтобы избежать чтения значений, которые наследуются через прототип объекта, просто проверьте, принадлежит ли свойство объекту:Кроме того, в ECMAScript 5 добавлен
forEach
метод,Array.prototype
который можно использовать для перечисления по массиву с помощью функции обратного вызова (polyfill находится в документации, поэтому вы все равно можете использовать его для старых браузеров):Важно отметить, что
Array.prototype.forEach
он не прерывается, когда возвращается обратный вызовfalse
. jQuery и Underscore.js предоставляют свои собственные вариантыeach
для обеспечения циклов, которые могут быть закорочены.источник
each
методы, позволяющиеreturn false
использовать их для выхода из цикла, ноforEach
это не вариант. Можно использовать внешний флаг (т .if (flag) return;
forEach
Если вы хотите зациклить массив, используйте стандартный
for
цикл из трех частей .Вы можете добиться некоторой оптимизации производительности, кэшируя
myArray.length
или перебирая ее в обратном порядке.источник
length
. ;),
после назначения не вводит новый глобальный, так что ваше предложение просто отлично ! Я путал это с другой проблемой: использование=
после присваивания создает новый глобал.var i, length, arrayItem;
перед циклом, чтобы избежать этого недоразумения.Я знаю, что это старый пост, и уже есть так много хороших ответов. Для большей полноты я решил добавить еще один, используя AngularJS . Конечно, это применимо только в том случае, если вы используете Angular, но, тем не менее, я бы все равно хотел его поставить.
angular.forEach
принимает 2 аргумента и необязательный третий аргумент. Первый аргумент - это объект (массив) для итерации, второй аргумент - это функция итератора, а необязательный третий аргумент - это контекст объекта (в основном называемый внутри цикла как «this»).Существуют разные способы использования цикла forEach angular. Самый простой и, вероятно, самый используемый
Еще один способ, который полезен для копирования элементов из одного массива в другой,
Хотя вам не нужно этого делать, вы можете просто сделать следующее, и это эквивалентно предыдущему примеру:
Теперь есть плюсы и минусы использования этой
angular.forEach
функции в отличие от встроенногоfor
цикла со вкусом ванили .Pros
angular.forEach
будет использовать цикл ES5 forEach. Теперь я доберусь до эффективности в разделе «против», поскольку циклы forEach намного медленнее, чем циклы for. Я упоминаю это как профессионал, потому что приятно быть последовательным и стандартизированным.Рассмотрим следующие 2 вложенных цикла, которые делают одно и то же. Допустим, у нас есть 2 массива объектов, и каждый объект содержит массив результатов, каждый из которых имеет свойство Value, являющееся строкой (или чем-то еще). И скажем, нам нужно перебрать каждый из результатов и, если они равны, выполнить некоторое действие:
Конечно, это очень простой гипотетический пример, но я написал тройной встроенный цикл, используя второй подход, и его было очень трудно читать и писать по этому вопросу.
Cons
angular.forEach
и нативныйforEach
, в этом отношении, оба намного медленнее, чем нормальныйfor
цикл ... примерно на 90% медленнее . Поэтому для больших наборов данных лучше придерживаться собственногоfor
цикла.continue
на самом деле поддерживается « случайностью », для продолженияangular.forEach
вы просто помещаетеreturn;
в функцию оператор типа,angular.forEach(array, function(item) { if (someConditionIsTrue) return; });
который заставит его выйти из функции для этой итерации. Это также связано с тем, что нативforEach
не поддерживает перерыв или продолжить.Я уверен, что есть и другие плюсы и минусы, и, пожалуйста, не стесняйтесь добавлять любые, которые вы считаете нужными. Я чувствую, что в итоге, если вам нужна эффективность, придерживайтесь только нативного
for
цикла для ваших циклов. Но, если ваши наборы данных меньше и с некоторой эффективностью можно отказаться в обмен на удобочитаемость и доступность для записи, то непременно добавьтеangular.forEach
этого плохого парня.источник
Если вы не против очистки массива:
x
будет содержать последнее значениеy
и будет удалено из массива. Вы также можете использоватьshift()
который даст и удалит первый элемент изy
.источник
[1, 2, undefined, 3]
.[1, 2, 0, 3]
или[true, true, false, true]
Foreach реализации ( см в jsFiddle ):
источник
Вероятно,
for(i = 0; i < array.length; i++)
петля не лучший выбор. Почему? Если у вас есть это:Метод будет вызываться из
array[0]
вarray[2]
. Во-первых, это будет сначала ссылаться на переменные, которых у вас даже нет, во-вторых, у вас не будет переменных в массиве, и в-третьих, это сделает код более смелым. Посмотрите здесь, это то, что я использую:И если вы хотите, чтобы это была функция, вы можете сделать это:
Если вы хотите сломаться, немного больше логики:
Пример:
Возвращает:
источник
Есть три реализации
foreach
в JQuery следующим образом .источник
Начиная с ECMAScript 6:
Где
of
избегает странностей, связанных сin
и заставляет его работать какfor
цикл любого другого языка, иlet
связываетсяi
внутри цикла, а не внутри функции.Скобки (
{}
) могут быть опущены, когда есть только одна команда (например, в примере выше).источник
Простым решением сейчас будет использование библиотеки underscore.js . Он предоставляет много полезных инструментов, таких как
each
и автоматически делегирует работу нативной,forEach
если она доступна.Пример CodePen о том, как это работает:
Смотрите также
Array.prototype.forEach()
.for each (variable in object)
это устарело как часть стандарта ECMA-357 ( EAX ).for (variable of object)
в качестве части предложения Harmony (ECMAScript 6).источник
Там нет никакого
for each
цикла в нативном JavaScript . Вы можете использовать библиотеки, чтобы получить эту функциональность (я рекомендую Underscore.js ), используйте простойfor
цикл.Однако обратите внимание, что могут быть причины использовать еще более простой
for
цикл (см. Вопрос переполнения стека. Почему использование «for… in» с итерацией массива является плохой идеей? )источник
Это итератор для не разреженного списка, где индекс начинается с 0, что является типичным сценарием при работе с document.getElementsByTagName или document.querySelectorAll)
Примеры использования:
Пример № 1
Пример № 2
Каждый р-тег получает
class="blue"
Пример № 3
Каждый другой тег p получает
class="red"
>Пример № 4
И, наконец, первые 20 синих p-тегов заменены на зеленые.
Предостережение при использовании строки в качестве функции: функция создается вне контекста и должна использоваться только в том случае, если вы уверены в области видимости переменной. В противном случае лучше передавать функции там, где обзор более интуитивно понятен.
источник
Есть несколько способов перебрать массив в JavaScript, как показано ниже:
ибо - это самый распространенный . Полный блок кода для зацикливания
while - цикл пока условие выполнено. Вроде бы самая быстрая петля
do / while - также цикл по блоку кода, пока условие выполнено, будет выполняться как минимум один раз
Функциональные циклы -
forEach
,map
,filter
, иreduce
(они перебрать функции, но они используются , если вам нужно что - то делать с вашим массивом и т.д.Для получения дополнительной информации и примеров о функциональном программировании на массивах, смотрите пост в блоге. Функциональное программирование на JavaScript: отображение, фильтрация и уменьшение .
источник
forEach
это не «функциональный» цикл, поскольку он не возвращает новыйArray
(на самом деле он ничего не возвращает), он просто повторяется.ECMAScript 5 (версия на JavaScript) для работы с массивами:
forEach - выполняет итерацию по каждому элементу в массиве и делает с каждым элементом все, что вам нужно.
На всякий случай больше интересует работа над массивом с использованием некоторой встроенной функции.
map - создает новый массив с результатом функции обратного вызова. Этот метод хорошо использовать, когда вам нужно отформатировать элементы вашего массива.
уменьшить - как следует из названия, он сводит массив к одному значению, вызывая данную функцию, передавая текущий элемент и результат предыдущего выполнения.
Every - Возвращает true или false, если все элементы в массиве проходят тест в функции обратного вызова.
filter - Очень похоже на все, за исключением того, что filter возвращает массив с элементами, которые возвращают true данной функции.
источник
Там нет встроенной способности взломать
forEach
. Чтобы прервать выполнение, используйтеArray#some
как ниже:Это работает, потому что
some
возвращает true, как только любой из обратных вызовов, выполненных в порядке массива, возвращает true, замыкая выполнение остальных. Оригинальный ответ см. Прототип Array для некоторыхисточник
Я также хотел бы добавить это как композицию обратного цикла и ответ выше для кого-то, кто также хотел бы этот синтаксис.
Плюсы:
Преимущество для этого: у вас есть ссылка уже в первом, как, что не нужно будет объявлять позже с другой строкой. Это удобно при зацикливании через массив объектов.
Минусы:
Это будет прерываться всякий раз, когда ссылка неверна - Falsey (неопределенный и т. Д.). Это может быть использовано как преимущество, хотя. Тем не менее, это будет немного сложнее для чтения. А также, в зависимости от браузера, его можно «не» оптимизировать, чтобы он работал быстрее оригинального.
источник
JQuery способ использования
$.map
:источник
[undefined, 2, undefined, 4, undefined, 6, undefined]
.Использование циклов с деструктуризацией ECMAScript 6 и оператором распространения
Разрушение и использование оператора распространения оказалось весьма полезным для новичков в ECMAScript 6 как более удобочитаемый / эстетичный, хотя некоторые ветераны JavaScript могут посчитать это грязным. Юниоры или другие люди могут найти это полезным.
Пример 1: Обычный
for...of
цикл - здесь никаких хитростей.Пример 2: разделение слов на символы
Пример 3: цикл с
key
иvalue
Пример 4: Получить свойства объекта встроенными
Пример 5: Получить глубокие свойства объекта того, что вам нужно
Пример 6: Используется ли Пример 3 с
.forEach
Пример 7: Используется ли Пример 4 с
.forEach
Пример 8: Является ли пример 5 используется с
.forEach
источник
Самый близкий к вашей идее способ - использовать
Array.forEach()
функцию закрытия, которая будет выполняться для каждого элемента массива.Другим жизнеспособным способом было бы использовать
Array.map()
метод, который работает таким же образом, но он также принимает все возвращаемые значения и возвращает их в новом массиве (по существу, отображая каждый элемент в новый), например так:источник
map
не изменяет элементы массива, поскольку возвращает новый массив, а элементы этого нового являются результатом применения функции к элементам старого массива.Вы можете позвонить forEach, как это:
forEach
будет выполнять итерацию по предоставленному вами массиву, и для каждой итерации будет иметьelement
значение этой итерации. Если вам нужен индекс, вы можете получить текущий индекс, передав вi
качестве второго параметра функцию обратного вызова для forEach.Foreach - это в основном функция высокого порядка, которая принимает в качестве параметра другую функцию.
Вывод:
Вы также можете перебрать массив так:
источник
Если вы хотите перебрать массив объектов с помощью функции стрелки:
источник
Лямбда-синтаксис обычно не работает в Internet Explorer 10 или ниже.
Я обычно использую
Если вы являетесь поклонником jQuery и у вас уже запущен файл jQuery, вам следует поменять местами позиции индекса и значения параметров
источник
Если у вас есть массивный массив, вы должны использовать,
iterators
чтобы получить некоторую эффективность. Итераторы свойство некоторых коллекций JavaScript (какMap
,Set
,String
,Array
). Дажеfor..of
используетiterator
под капотом.Итераторы повышают эффективность, позволяя вам использовать элементы списка по одному, как если бы они были потоком. Что делает итератор особенным, так это то, как он пересекает коллекцию. Другие циклы должны загружать всю коллекцию заранее, чтобы выполнить итерацию, тогда как итератору нужно знать только текущую позицию в коллекции.
Вы получаете доступ к текущему элементу, вызывая метод итератора
next
. Следующий метод вернетvalue
текущий элемент и a,boolean
чтобы указать, когда вы достигли конца коллекции. Ниже приведен пример создания итератора из массива.Преобразуйте ваш обычный массив в итератор, используя
values()
метод, подобный этому:Вы также можете преобразовать свой обычный массив в итератор, используя
Symbol.iterator
это:Вы также можете преобразовать свой обычный
array
вiterator
подобное:ПРИМЕЧАНИЕ :
iterable
по умолчанию. Используйтеfor..in
в этом случае, потому что вместо значений он работает с ключами.Вы можете прочитать больше о
iteration protocol
здесь .источник
Если вы хотите использовать
forEach()
, это будет выглядеть так -Если вы хотите использовать
for()
, это будет выглядеть так -источник
Согласно новой обновленной функции ECMAScript 6 (ES6) и ECMAScript 2015, вы можете использовать следующие параметры с циклами:
источник
Представление
Сегодня (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
тестыwhile
тестыПоказать фрагмент кода
Результаты кросс-браузер
Результаты для всех протестированных браузеров
браузеры **
Массив с 10 элементами
Результаты для Chrome. Вы можете выполнить тест на вашей машине здесь .
Массив с 1 000 000 элементов
Результаты для Chrome. Вы можете выполнить тест на вашей машине здесь
источник
Резюме:
При переборе массива мы часто хотим выполнить одну из следующих целей:
Мы хотим перебрать массив и создать новый массив:
Array.prototype.map
Мы хотим перебрать массив и не создавать новый массив:
Array.prototype.forEach
for..of
петляВ JavaScript есть много способов достижения обеих этих целей. Однако некоторые из них более удобны, чем другие. Ниже вы можете найти некоторые часто используемые методы (наиболее удобный IMO) для выполнения итерации массива в JavaScript.
Создание нового массива:
Map
map()
это функция,Array.prototype
которая может преобразовать каждый элемент массива, а затем вернуть новый массив.map()
принимает в качестве аргумента функцию обратного вызова и работает следующим образом:Обратный вызов, который мы передали в
map()
качестве аргумента, выполняется для каждого элемента. Затем возвращается массив, который имеет ту же длину, что и исходный массив. В этом новом элементе массива преобразовывается функция обратного вызова, переданная в качестве аргументаmap()
.Различия между
map
другим циклическим механизмом, подобным циклу,forEach
иfor..of
циклом, которыйmap
возвращает новый массив и оставляет старый массив без изменений (за исключением случаев, когда вы явно манипулируете им с помощью мышленияsplice
).Также обратите внимание, что
map
обратный вызов функции предоставляет порядковый номер текущей итерации в качестве второго аргумента. Кроме того, третий аргумент предоставляет массив, на которомmap
был вызван? Иногда эти свойства могут быть очень полезными.Использование петли
forEach
forEach
является функцией, которая находится в функции, котораяArray.prototype
принимает функцию обратного вызова в качестве аргумента. Затем он выполняет эту функцию обратного вызова для каждого элемента в массиве. В отличие отmap()
функции, функция forEach ничего не возвращает (undefined
). Например:Как и
map
функция,forEach
обратный вызов предоставляет порядковый номер текущей итерации в качестве второго аргумента. Кроме того, третий аргумент предоставляет массив, на которомforEach
был вызван?Перебирать элементы, используя
for..of
for..of
Петли петли через каждый элемент массива (или любого другого объекта Iterable). Это работает следующим образом:В приведенном выше примере
element
обозначает элемент массива иarr
является массивом, который мы хотим зациклить. Обратите внимание, что имяelement
является произвольным, и мы могли бы выбрать любое другое имя, например «el», или что-то более декларативное, когда это применимо.Не путайте
for..in
петлю сfor..of
петлей.for..in
будет проходить через все перечисляемые свойства массива, тогда какfor..of
цикл будет проходить только через элементы массива. Например:источник