Перебрать массив в JavaScript

3149

В Java вы можете использовать forцикл для обхода объектов в массиве следующим образом:

String[] myStringArray = {"Hello", "World"};
for (String s : myStringArray)
{
    // Do something
}

Можете ли вы сделать то же самое в JavaScript?

Марк Шиманский
источник
5
Итак, я немного запутался, можно ли использовать расширенный цикл for при доступе к объектам? И использовать последовательный для заполнения? Это правильно?
Марк Шимански
45
нет, это действительно просто, объекты массива имеют числовые индексы, поэтому вы хотите выполнить итерацию по этим индексам в числовом порядке, последовательный цикл гарантирует, что расширенный for-in цикл перечисляет свойства объекта без определенного порядка, а также перечисляет унаследованные свойства. .. для перебора массивов всегда рекомендуется использовать последовательные циклы ...
CMS
2
связанные - stackoverflow.com/questions/5349425/…
jondavidjohn
6
jsben.ch/#/Q9oD5 <= Вот эталон из множества решений для циклического
перемещения
3
@ CMS Нет, не все так просто. Это действительно просто на любом другом языке. Это нелепо сложно в JS, где у вас есть, inи ofэто можно использовать и делать разные вещи. Тогда у вас также есть forEachи уродливый и раздражающий цикл на основе индекса. Любой другой современный язык делает зацикливание на коллекции простым и понятным, без сюрпризов и путаницы. JS тоже может, но это не так.
jpmc26

Ответы:

3966

У вас есть несколько вариантов:

1. Последовательный forцикл:

var myStringArray = ["Hello","World"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
    console.log(myStringArray[i]);
    //Do something
}

Pros

  • Работает в любой среде
  • Вы можете использовать breakи continueоператоры управления потоком

Cons

  • Слишком многословно
  • Императив
  • Легко иметь отдельные ошибки (иногда их также называют ошибкой поста забора )

2. Array.prototype.forEach

Спецификация ES5 представила множество полезных методов массива, один из них, Array.prototype.forEachи он дает нам краткий способ перебора массива:

const array = ["one", "two", "three"]
array.forEach(function (item, index) {
  console.log(item, index);
});

Прошло почти десять лет с момента написания спецификации ES5 (декабрь 2009 г.), и она была реализована практически всеми современными механизмами в настольных, серверных и мобильных средах, поэтому их безопасно использовать.

А с синтаксисом функции стрелки ES6 это еще более кратко:

array.forEach(item => console.log(item));

Функции со стрелками также широко применяются, если только вы не планируете поддерживать древние платформы (например, IE11); ты тоже в безопасности.

Pros

  • Очень коротко и лаконично.
  • декларативный

Cons

  • Не могу использовать break/continue

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

array.filter(item => item.condition < 10)
     .forEach(item => console.log(item))

Имейте в виду, что если вы итерируете массив для создания другого массива из него , вы должны использовать map, я видел этот анти-паттерн много раз.

Анти-шаблон:

const numbers = [1,2,3,4,5], doubled = [];

numbers.forEach((n, i) => { doubled[i] = n * 2 });

Правильный вариант использования карты :

const numbers = [1,2,3,4,5];
const doubled = numbers.map(n => n * 2);

console.log(doubled);

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

Анти-шаблон:

const numbers = [1,2,3,4,5];
const sum = 0;
numbers.forEach(num => { sum += num });

Правильное использование уменьшить :

const numbers = [1,2,3,4,5];
const sum = numbers.reduce((total, n) => total + n, 0);

console.log(sum);

3. for-ofЗаявление ES6

Стандарт ES6 вводит концепцию итерируемых объектов и определяет новую конструкцию для прохождения данных - for...ofоператор.

Этот оператор работает для любого типа итерируемого объекта, а также для генераторов (любого объекта, у которого есть [Symbol.iterator]свойство).

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

let colors = ['red', 'green', 'blue'];
for (const color of colors){
    console.log(color);
}

Pros

  • Он может перебирать большое разнообразие объектов.
  • Можно использовать обычные операторы управления потоком ( break/continue ).
  • Полезно для последовательной итерации асинхронных значений.

Cons

  • Если вы ориентируетесь на более старые браузеры, транспонированный вывод может вас удивить .

Не используйте for...in

@zipcodeman предлагает использовать for...inоператор, но для итерации массивов for-inследует избегать, этот оператор предназначен для перечисления свойств объекта.

Он не должен использоваться для объектов, подобных массиву, потому что:

  • Порядок итерации не гарантируется; индексы массива нельзя посещать в числовом порядке.
  • Унаследованные свойства также перечислены.

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

Например:

Array.prototype.foo = "foo!";
var array = ['a', 'b', 'c'];

for (var i in array) {
    console.log(array[i]);
}

Приведенный выше код будет консоль журнала "a", "b", "c" и "foo!".

Это может быть особенно проблемой, если вы используете какую-то библиотеку, которая в значительной степени опирается на расширение собственных прототипов (например, MooTools).

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

var obj = {
    "a": 1,
    "b": 2,
    "c": 3
};

for (var prop in obj) {
    if (obj.hasOwnProperty(prop)) { 
        // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
        console.log("prop: " + prop + " value: " + obj[prop])
    }
}

В приведенном выше примере hasOwnPropertyметод позволяет перечислять только собственные свойства , вот и все, только те свойства, которые физически имеет объект, без унаследованных свойств.

Я бы порекомендовал вам прочитать следующую статью:

CMS
источник
21
Это причина (по его собственным данным CMS) stackoverflow.com/questions/1885317/…
OscarRyz
15
@DoubleGras, я думаю, что это мнение не всех разделяет. См .: stackoverflow.com/questions/5752906/… or groups.google.com/forum/?fromgroups#!topic/jsmentors/…
Маттис Вессельс
3
Любой, кто думает, что вам нужно кешировать длину ... Пожалуйста, посмотрите мой ответ, вам даже не нужно обращаться к нему один раз, не говоря уже о кешировании: for (var i = 0, item; item = myStringArray [i]; i ++) {/ * используйте элемент здесь * /}
Stijn de Witt
15
@StijndeWitt Нет, потому что перерывы , если у вас есть какое - либо «falsey» значение в массиве: false, undefined, 0, "", NaN.
Phrogz
6
jsperf.com/caching-array-length/4 Вот тест, чтобы увидеть, стоит ли кэшировать длину массива в цикле Javascript
Энрико
1116

Да, если ваша реализация включает for...of функцию, представленную в ECMAScript 2015 (выпуск "Harmony") ... который в наши дни является довольно безопасным предположением.

Это работает так:

// REQUIRES ECMASCRIPT 2015+
var s, myStringArray = ["Hello", "World"];
for (s of myStringArray) {
  // ... do something with s ...
}

Или еще лучше, так как ECMAScript 2015 также предоставляет переменные в области блока:

// REQUIRES ECMASCRIPT 2015+
const myStringArray = ["Hello", "World"];
for (const s of myStringArray) {
  // ... do something with s ...
}
// s is no longer defined here

(Переменная sотличается на каждой итерации, но все еще может быть объявлена constвнутри тела цикла, если она там не изменена.)

Замечание о разреженных массивах: массив в JavaScript может на самом деле не хранить столько элементов, сколько сообщил его length; это сообщаемое число просто на единицу больше, чем самый высокий индекс, при котором хранится значение. Если массив содержит меньше элементов, чем указано в его длине, он называется разреженным . Например, вполне допустимо иметь массив с элементами только по индексам 3, 12 и 247; в s для любых недостающих элементов, или вы хотите обрабатывать только элементы фактически присутствующие? Существует множество приложений для обоих подходов; это зависит только от того, для чего вы используете массив.lengthтакого массива сообщается как 248, хотя на самом деле только хранить 3 значения. Если вы попытаетесь получить доступ к элементу по какому-либо другому индексу, массив будет иметь undefinedзначение там. Поэтому, когда вы хотите «пройтись» по массиву, у вас возникает вопрос: хотите ли вы пройтись по всему диапазону, указанному его длиной и процессом?undefined

Если вы выполняете итерацию массива с помощью for.. of, тело цикла выполняется lengthраз, а для переменной управления цикла устанавливается значение undefinedдля любых элементов, фактически не представленных в массиве. В зависимости от деталей вашего кода «делать что-то», такое поведение может быть тем, что вам нужно, но если нет, вам следует использовать другой подход.

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

Пока ваша реализация JavaScript совместима с предыдущей версией спецификации ECMAScript (которая исключает, например, версии Internet Explorer до 9), вы можете использовать Array#forEachметод итератора вместо цикла. В этом случае вы передаете функцию, которая будет вызываться для каждого элемента в массиве:

var myStringArray = [ "Hello", "World" ];
myStringArray.forEach( function(s) { 
     // ... do something with s ...
} );

В отличие от for... of, .forEachвызывает функцию только для элементов, которые действительно присутствуют в массиве. Если передать наш гипотетический массив с тремя элементами и длиной 248, он будет вызывать функцию только три раза, а не 248 раз. Он также различает отсутствующие элементы и элементы, которые на самом деле установлены undefined; для последнего он по-прежнему будет вызывать функцию, передавая undefinedв качестве аргумента. Если это, как вы хотите обрабатывать разреженные массивы, .forEachможет быть путь , даже если интерпретатор поддерживает for... of.

Последний вариант, который работает во всех версиях JavaScript, - это явный цикл подсчета . Вы просто считаете от 0 до единицы меньше длины и используете счетчик в качестве индекса. Основной цикл выглядит так:

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  s = myStringArray[i];
  // ... do something with s ...
}

Одним из преимуществ этого подхода является то, что вы можете выбрать способ обработки разреженных массивов; приведенный выше код будет работать тело цикла полные lengthраз, с sнабором для undefinedлюбых недостающих элементов, так же как for.. of. Если вы вместо этого хотите обрабатывать только реально существующие элементы разреженного массива, например .forEach, вы можете добавить простой inтест в индекс:

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  if (i in myStringArray) {
    s = myStringArray[i];
    // ... do something with s ...
  }
}

Присвоение значения длины локальной переменной (в отличие от включения полного myStringArray.lengthвыражения в условие цикла) может существенно повлиять на производительность, поскольку оно пропускает поиск свойств каждый раз; при использовании Rhino на моей машине ускорение составляет 43%.

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

var i, len, myStringArray = [ "Hello", "World" ];
for (len = myStringArray.length, i=0; i<len; ++i) {

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

myStringArray.forEach( function(s, i) {
   // ... do something with s and i ...
});

for... ofне дает индекс, связанный с каждым объектом, но пока объект, над которым вы перебираете, фактически является Array( for.. ofработает для других повторяемых типов, которые могут не иметь этого метода), вы можете использовать массив Метод #entries, чтобы изменить его на массив пар [index, item], а затем выполнить итерацию:

for (const [i, s] of myStringArray.entries()) {
  // ... do something with s and i ...
}

for... inсинтаксис уже отмечалось другими для цикла по свойствам объекта; так как массив в JavaScript - это просто объект с числовыми именами свойств (и автоматически обновляемым lengthсвойством), вы можете теоретически зациклить массив с ним. Но проблема заключается в том, что он не ограничивается числовыми значениями свойств (помните, что даже методы на самом деле являются просто свойствами, значение которых является замыканием), и при этом не гарантируется, что они будут повторяться в числовом порядке. Следовательно, синтаксис for... не должен использоваться для циклического перемещения по массивам.in

Марк Рид
источник
21
Обратите внимание, что некоторые интерпретаторы (например, V8) автоматически кэшируют длину массива, если код вызывается достаточное количество раз, и обнаруживает, что длина не изменяется циклом. Хотя кэширование длины по-прежнему полезно, оно может не обеспечить повышение скорости, когда ваш код вызывается достаточно много раз, чтобы реально изменить ситуацию.
Phrogz
2
@ mark-reed Не могли бы вы объяснить, почему вы использовали i in myStringArrayв своем примере? Как это может быть ложным?
Денис V
2
@DenisV: ложь. a=[1,2,3,4]; delete a[2]; for (j in a) { console.log(j); } выходы 0, 1, 3 и 4. a.lengthпо-прежнему 5.
Марк Рид
1
Я не предлагаю for j in a. Я демонстрирую, что inпроверка не является избыточной, как вы утверждали, показывая все индексы и показывая, что есть один между 0, а length-1его нет. Я мог бы также просто напечатать 2 in a, что действительно false, несмотря на то, что вы сказали, что это невозможно.
Марк Рид
2
@GrijeshChauhan - правильно. Например, IE до версии 8 не поддерживает его. Смотрите этот вопрос .
Марк Рид
442

Вы можете использовать mapэтот метод функционального программирования, который также доступен на других языках, таких как Python и Haskell .

[1,2,3,4].map( function(item) {
     alert(item);
})

Общий синтаксис:

array.map(func)

В общем случае funcбудет принимать один параметр, который является элементом массива. Но в случае JavaScript он может принимать второй параметр, который является индексом элемента, и третий параметр, который является самим массивом.

Возвращаемым значением array.mapявляется другой массив, поэтому вы можете использовать его следующим образом:

var x = [1,2,3,4].map( function(item) {return item * 10;});

И теперь х есть [10,20,30,40].

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

var item_processor = function(item) {
      // Do something complicated to an item
}

new_list = my_list.map(item_processor);

который будет в некотором роде эквивалентен:

 for (item in my_list) {item_processor(item);}

За исключением того, что вы не получите new_list.

Hasen
источник
7
Нет, но это может быть более мощным. проверить это: joelonsoftware.com/items/2006/08/01.html
hasen
97
Этот конкретный пример, вероятно, лучше реализовать с помощью Array.forEach. mapдля генерации нового массива.
Harto
21
@hasen, Array.prototype.mapметод является частью стандарта ECMAScript 5-й редакции, еще не доступен во всех реализациях (например, в IE его нет), также для итерации по массиву, я думаю, что Array.prototype.forEachметод более семантически корректен ... также, пожалуйста, не t-предложение, см. мой ответ для более подробной информации :)
CMS
3
Разница между forEachи mapзаключается в том, что первый не возвращает результаты итерации. map(иногда иначе collect, но очень отличается от apply) специально для преобразования каждого элемента массива в соответствующий результат; это отображение 1 к 1 , отсюда и название. Это часть целого семейства операций, которые включают reduce(который производит один результат из всего массива) и filter(который производит подмножество исходного массива) и так далее. В то время как forEachпросто что-то делает с каждым элементом, семантика не указана.
Марк Рид
4
Даунвот, потому что если вы на самом деле что-то не отображаете, то использование [] .map вводит в заблуждение. [] .forEach имеет смысловой смысл, а также передает те же три аргумента функции.
gengkev
120

В JavaScript не рекомендуется проходить через массив с циклом for-in, но лучше использовать forцикл, такой как:

for(var i=0, len=myArray.length; i < len; i++){}

Он также оптимизирован («кэширует» длину массива). Если вы хотите узнать больше, прочитайте мой пост на эту тему .

sebarmeli
источник
2
myArray.forEach (function (obj) {}); все еще лучший
Ян Сверре
крошечное улучшение: вы можете использовать ++iвместоi++
roberkules
14
++iэто оптимизация старой школы, которую современные компиляторы делают для вас в цикле for уже давно :) stackoverflow.com/a/1547433/1033348
ngryman
6
Вы должны быть осторожны, используя этот цикл. Я начал использовать его, и мне было сложно отследить ошибку из-за одной ошибки, которую я сделал. Если вы вложите два цикла, как это: jsfiddle.net/KQwmL/1 . Вы должны быть осторожны, чтобы по-разному называть переменную в двух циклах, иначе вторая петля заменит первую длину.
Руи Маркес
1
Руи Маркес - вы можете назвать свою переменную i_stopили i_endвместо len. Он так же удобочитаем (если не больше!), И вы, естественно, избежите такого рода проблем (поскольку ваш другой цикл получит, например, j_stop).
Чип Хогг
119

for (пусть из myStringArray) {

(Непосредственно отвечая на ваш вопрос: теперь вы можете!)

Большинство других ответов верны, но они не упоминают (на момент написания статьи), что в ECMA Script  6  2015 появился новый механизм выполнения итерации - for..ofцикл.

Этот новый синтаксис является наиболее элегантным способом итерации массива в javascript (если вам не нужен индекс итерации).

В настоящее время он работает с Firefox 13+, Chrome 37+ и изначально не работает с другими браузерами (см. Совместимость браузера ниже). К счастью, у нас есть JS-компиляторы (такие как Babel ), которые позволяют нам использовать функции следующего поколения сегодня.

Он также работает на узле (я тестировал его на версии 0.12.0).

Итерация массива

// You could also use "let" instead of "var" for block scope.
for (var letter of ["a", "b", "c"]) { 
   console.log(letter); 
}

Итерация массива объектов

var band = [
  {firstName : 'John', lastName: 'Lennon'}, 
  {firstName : 'Paul', lastName: 'McCartney'}
];

for(var member of band){
  console.log(member.firstName + ' ' + member.lastName); 
}

Итерация генератора:

(пример извлечен из https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of )

function* fibonacci() { // a generator function
  let [prev, curr] = [1, 1];
  while (true) {
    [prev, curr] = [curr, prev + curr];
    yield curr;
  }
}

for (let n of fibonacci()) {
  console.log(n);
  // truncate the sequence at 1000
  if (n >= 1000) {
    break;
  }
}

Таблица совместимости: http://kangax.github.io/es5-compat-table/es6/#For..of циклов

Spec: http://wiki.ecmascript.org/doku.php?id=harmony:iterators

}

Марлон Бернардес
источник
Если вы используете ES6, я бы предложил const sвместоvar s
joeytwiddle
В моих тестах на больших массивах время var s of arrвыполнения почти удвоилось (в 1,9 раза) по сравнению с использованием простого счетчика цикла for и извлечения элементов по индексу в nodejs
theferrit32
Почему эти странные вещи в первой и последней строке?
Питер Мортенсен
91

Opera, Safari, Firefox и Chrome теперь все совместно используют набор улучшенных методов Array для оптимизации многих распространенных циклов.

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

Mozilla Labs опубликовала алгоритмы, которые они и WebKit используют, так что вы можете добавить их самостоятельно.

Фильтр возвращает массив элементов, которые удовлетворяют некоторому условию или тесту.

each возвращает true, если каждый член массива проходит тест.

некоторые возвращают истину, если они проходят тест.

forEach запускает функцию для каждого члена массива и ничего не возвращает.

Карта похожа на forEach, но она возвращает массив результатов операции для каждого элемента.

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

Игнорируйте это, пока вам это не нужно.

indexOf и lastIndexOf находят подходящую позицию первого или последнего элемента, которая точно соответствует его аргументу.

(function(){
    var p, ap= Array.prototype, p2={
        filter: function(fun, scope){
            var L= this.length, A= [], i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        val= this[i];
                        if(fun.call(scope, val, i, this)){
                            A[A.length]= val;
                        }
                    }
                    ++i;
                }
            }
            return A;
        },
        every: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && !fun.call(scope, this[i], i, this))
                        return false;
                    ++i;
                }
                return true;
            }
            return null;
        },
        forEach: function(fun, scope){
            var L= this.length, i= 0;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
            }
            return this;
        },
        indexOf: function(what, i){
            i= i || 0;
            var L= this.length;
            while(i< L){
                if(this[i]=== what)
                    return i;
                ++i;
            }
            return -1;
        },
        lastIndexOf: function(what, i){
            var L= this.length;
            i= i || L-1;
            if(isNaN(i) || i>= L)
                i= L-1;
            else
                if(i< 0) i += L;
            while(i> -1){
                if(this[i]=== what)
                    return i;
                --i;
            }
            return -1;
        },
        map: function(fun, scope){
            var L= this.length, A= Array(this.length), i= 0, val;
            if(typeof fun== 'function'){
                while(i< L){
                    if(i in this){
                        A[i]= fun.call(scope, this[i], i, this);
                    }
                    ++i;
                }
                return A;
            }
        },
        some: function(fun, scope){
            var i= 0, L= this.length;
            if(typeof fun== 'function'){
                while(i<L){
                    if(i in this && fun.call(scope, this[i], i, this))
                        return true;
                    ++i;
                }
                return false;
            }
        }
    }
    for(p in p2){
        if(!ap[p])
            ap[p]= p2[p];
    }
    return true;
})();
Kennebec
источник
1
Дополнение: IE поддерживает forEach начиная с версии 9, см. Метод forEach MSDN
rwitzel
75

вступление

Со времени учебы в колледже я программировал на Java, JavaScript, Pascal, ABAP учился , PHP, Progress 4GL, C / C ++ и, возможно, на некоторых других языках, о которых я не могу думать сейчас.

Хотя все они имеют свои собственные лингвистические особенности, каждый из этих языков имеет много общих базовых понятий. Такие понятия включают процедуры / функции, IF-statements, FOR-loops и WHILE-loops.


Традиционная forпетля

Традиционный forцикл состоит из трех компонентов:

  1. Инициализация: выполняется перед первым выполнением блока просмотра
  2. Условие: проверяет условие каждый раз перед выполнением блока цикла и выходит из цикла, если false
  3. Запоздалая мысль: выполняется каждый раз после выполнения цикла цикла

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

for (;;) {
    // Do stuff
}

Конечно, вам нужно будет включить if(condition === true) { break; } или if(condition === true) { return; }где-то внутри этого for-loop, чтобы заставить его перестать работать.

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

for (var i = 0, length = 10; i < length; i++) {
    console.log(i);
}

Использование традиционного forцикла для обхода массива

Традиционный способ перебрать массив:

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

Или, если вы предпочитаете цикл в обратном направлении, вы делаете это:

for (var i = myArray.length - 1; i > -1; i--) {
    console.log(myArray[i]);
}

Однако возможны многие варианты, например, такие:

for (var key = 0, value = myArray[key], length = myArray.length; key < length; value = myArray[++key]) {
    console.log(value);
}

... или этот ...

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

... или этот:

var key = 0, value;
for (; value = myArray[key++];){
    console.log(value);
}

То, что работает лучше всего, в значительной степени зависит как от личного вкуса, так и от конкретного варианта использования, который вы реализуете.

Обратите внимание, что каждый из этих вариантов поддерживается всеми браузерами, включая очень старые!


whileцикл

Одной из альтернатив forцикла является whileцикл. Чтобы перебрать массив, вы можете сделать это:

var key = 0;
while(value = myArray[key++]){
    console.log(value);
}

Как и традиционные forциклы, whileциклы поддерживаются даже в самых старых браузерах.

Также обратите внимание, что каждый цикл while можно переписать как forцикл. Например, приведенный whileвыше цикл ведет себя точно так же, как этот for-loop:

for(var key = 0; value = myArray[key++];){
    console.log(value);
}

For...in а также for...of

В JavaScript вы также можете сделать это:

for (i in myArray) {
    console.log(myArray[i]);
}

Однако это следует использовать с осторожностью, поскольку оно не ведет себя так же, как традиционный forцикл во всех случаях, и существуют потенциальные побочные эффекты, которые необходимо учитывать. См. Почему использование «for ... in» с итерацией массива - плохая идея? Больше подробностей.

Как альтернатива for...in, теперь есть и для for...of. В следующем примере показана разница между for...ofциклом и for...inциклом:

var myArray = [3, 5, 7];
myArray.foo = "hello";

for (var i in myArray) {
  console.log(i); // logs 0, 1, 2, "foo"
}

for (var i of myArray) {
  console.log(i); // logs 3, 5, 7
}

Кроме того, вы должны учитывать, что ни одна из версий Internet Explorer не поддерживает for...of( Edge 12+ ) и for...inтребует как минимум Internet Explorer 10.


Array.prototype.forEach()

Альтернативой for-loops является Array.prototype.forEach()следующий синтаксис:

myArray.forEach(function(value, key, myArray) {
    console.log(value);
});

Array.prototype.forEach() поддерживается всеми современными браузерами, а также Internet Explorer 9 и более поздними версиями.


Библиотеки

Наконец, многие служебные библиотеки также имеют свои собственные foreachварианты. AFAIK, три самых популярных из них:

jQuery.each()в jQuery :

$.each(myArray, function(key, value) {
    console.log(value);
});

_.each()в Underscore.js :

_.each(myArray, function(value, key, myArray) {
    console.log(value);
});

_.forEach(), в Lodash.js :

_.forEach(myArray, function(value, key) {
    console.log(value);
});
Джон Слегерс
источник
68

Используйте цикл while ...

var i=0, item, items = ['one','two','three'];
while(item = items[i++]){
    console.log(item);
}

журналы: «один», «два», «три»

И для обратного порядка, еще более эффективный цикл

var items = ['one','two','three'], i = items.length;
while(i--){
    console.log(items[i]);
}

журналы: «три», «два», «один»

Или классическая forпетля

var items = ['one','two','three']
for(var i=0, l = items.length; i < l; i++){
    console.log(items[i]);
}

журналы: «один», «два», «три»

Ссылка: http://www.sitepoint.com/google-closure-how-not-to-write-javascript/

Тимо Хуовинен
источник
21
Первый пример синтаксиса while не будет работать, если какой-либо из элементов массива будет ложным.
Крис Купер
2
... и этот цикл while эквивалентен: for (var i = 0, item; item = items [i]; i ++), что избавляет от необходимости заранее объявлять переменные index и item ...
Stijn de Witt
39

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

for (var i=myArray.length;i--;){
  var item=myArray[i];
}

Это имеет преимущество кэширования длины (аналогично for (var i=0, len=myArray.length; i<len; ++i)и в отличие отfor (var i=0; i<myArray.length; ++i) ) при меньшем наборе символов.

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

Phrogz
источник
16
Для людей, которые не понимают, что такого гениального: сначала вычисляется выражение i-- и позволяет циклу продолжаться, когда оно не ложно ... После этого счетчик уменьшается. Как только я стану равным нулю, он выйдет из цикла, так как ноль - ложное значение в Javascript.
Стейн де Витт
5
falsish? Ты имеешь в виду фальси. Давайте все придерживаться правильной терминологии, чтобы избежать путаницы;)
danwellman
4
Я видел термин «фальшивка», который используют люди, которых я считаю гуру. Если это достаточно хорошо для них, это достаточно хорошо для меня. Также, но разочарован, увидев, что мой комментарий, который на самом деле онтопичен и добавляет объяснение / понимание, получает 0 голосов, но комментарий, который придирается к термину в моем комментарии, получает 4. Ну, я думаю, это просто вопрос приоритетов.
Стейн де Витт
"Кэширование длины"? Длина сохраняется как целое число в массиве, она не измеряется каждый раз, когда вы обращаетесь к нему. Здесь нет смысла копировать значение длины в другую переменную.
Разное
1
@ Разное В эти дни, конечно, нет; в прошлые годы итерирование массивов JavaScript, кэширование длины на стороне JavaScript (вместо достижения всей реализации) было явным преимуществом (при микрооптимизации). Например, for (var i=0,len=array.length;i<len;++i)был общий, разумный цикл для записи.
Phrogz
36

Некоторые случаи использования циклического перемещения по массиву в функциональном программировании в JavaScript:

1. Просто перебрать массив

const myArray = [{x:100}, {x:200}, {x:300}];

myArray.forEach((element, index, array) => {
    console.log(element.x); // 100, 200, 300
    console.log(index); // 0, 1, 2
    console.log(array); // same myArray object 3 times
});

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

2. Проверьте, проходит ли какой-либо из элементов массива тест

const people = [
    {name: 'John', age: 23}, 
    {name: 'Andrew', age: 3}, 
    {name: 'Peter', age: 8}, 
    {name: 'Hanna', age: 14}, 
    {name: 'Adam', age: 37}];

const anyAdult = people.some(person => person.age >= 18);
console.log(anyAdult); // true

3. Преобразовать в новый массив

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray= myArray.map(element => element.x);
console.log(newArray); // [100, 200, 300]

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

4. Подведите итог конкретного свойства и рассчитайте его среднее

const myArray = [{x:100}, {x:200}, {x:300}];

const sum = myArray.map(element => element.x).reduce((a, b) => a + b, 0);
console.log(sum); // 600 = 0 + 100 + 200 + 300

const average = sum / myArray.length;
console.log(average); // 200

5. Создайте новый массив на основе оригинала, но не изменяя его

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray= myArray.map(element => {
    return {
        ...element,
        x: element.x * 2
    };
});

console.log(myArray); // [100, 200, 300]
console.log(newArray); // [200, 400, 600]

6. Подсчитайте количество каждой категории

const people = [
    {name: 'John', group: 'A'}, 
    {name: 'Andrew', group: 'C'}, 
    {name: 'Peter', group: 'A'}, 
    {name: 'James', group: 'B'}, 
    {name: 'Hanna', group: 'A'}, 
    {name: 'Adam', group: 'B'}];

const groupInfo = people.reduce((groups, person) => {
    const {A = 0, B = 0, C = 0} = groups;
    if (person.group === 'A') {
        return {...groups, A: A + 1};
    } else if (person.group === 'B') {
        return {...groups, B: B + 1};
    } else {
        return {...groups, C: C + 1};
    }
}, {});

console.log(groupInfo); // {A: 3, C: 1, B: 2}

7. Получить подмножество массива на основе определенных критериев

const myArray = [{x:100}, {x:200}, {x:300}];

const newArray = myArray.filter(element => element.x > 250);
console.log(newArray); // [{x:300}] 

Примечание. Метод filter () создает новый массив со всеми элементами, которые проходят тест, реализованный предоставленной функцией.

8. Сортировать массив

const people = [
  { name: "John", age: 21 },
  { name: "Peter", age: 31 },
  { name: "Andrew", age: 29 },
  { name: "Thomas", age: 25 }
];

let sortByAge = people.sort(function (p1, p2) {
  return p1.age - p2.age;
});

console.log(sortByAge);

введите описание изображения здесь

9. Найти элемент в массиве

const people = [ {name: "john", age:23},
                {name: "john", age:43},
                {name: "jim", age:101},
                {name: "bob", age:67} ];

const john = people.find(person => person.name === 'john');
console.log(john);

введите описание изображения здесь

Метод Array.prototype.find () возвращает значение первого элемента в массиве, которое удовлетворяет предоставленной функции тестирования.

Ссылки

Юйцы
источник
30

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

var i = 0,
     item;

// note this is weak to sparse arrays or falsey values
for ( ; item = myStringArray[i++] ; ){ 
    item; // This is the string at the index.
}

Или, если вы действительно хотите получить идентификатор и получить действительно классический forцикл:

var i = 0,
    len = myStringArray.length; // cache the length

for ( ; i < len ; i++ ){
    myStringArray[i]; // Don't use this if you plan on changing the length of the array
}

Современные браузеры всех методы поддержки итераторов forEach, map, reduce, filterа также множество других методов на массив прототипе .

Габриель
источник
3
Обратите внимание, что некоторые интерпретаторы (например, V8) автоматически кэшируют длину массива, если код вызывается достаточное количество раз, и обнаруживает, что длина не изменяется циклом.
Phrogz
Спасибо за информацию @Phrogz, это правда, что виртуальная машина может выполнить множество оптимизаций, но, поскольку в старых браузерах ее нет, лучше бы оптимизировать ее, так как она очень дешевая.
Габриэль
1
@ Габриэль: почему? Пожалуйста, приведите примеры из реальной жизни, показывающие, что отсутствие кэширования длины на самом деле является узким местом производительности. Я придерживаюсь подхода «преждевременная оптимизация - корень зла». Я исправлю этот цикл, который на самом деле создает проблему, как только я столкнусь с ним ...
Stijn de Witt
1
@StijndeWitt IMO это просто стилистическая проблема. Честно говоря, я больше не использую циклы, вместо этого полагаясь на подчеркивание для таких вещей, как _.each, _.map и т. Д. Для выполнения этих задач. Когда я делал подобные циклы, я кэшировал длину в основном так, чтобы все мои объявления переменных были в одном месте, в верхней части моей функции. Следование моим советам в этом отношении не имеет значения для любого реального применения. Преждевременная оптимизация - это очень плохо, но если оптимизация происходит в результате стилистических решений, я не думаю, что это действительно имеет значение.
Габриэль
1
@ Габриэль Я полагаю, что JavaScript уже поддерживает функцию map для массивов, для этого не нужно вводить дополнительную библиотеку.
Noz
28

Существуют различные способы просмотра массива в JavaScript.

Общий цикл:

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

ES5 для каждого:

substr.forEach(function(item) {
    // Do something with `item`
});

jQuery.each:

jQuery.each(substr, function(index, item) {
    // Do something with `item` (or `this` is also `item` if you like)
});

Посмотрите это для получения подробной информации или вы также можете проверить MDN для циклического прохождения массива в JavaScript и использования jQuery для проверки jQuery для каждого .

RizN81
источник
27

Я бы настоятельно рекомендовал использовать библиотеку underscore.js . Он предоставляет вам различные функции, которые вы можете использовать для перебора массивов / коллекций.

Например:

_.each([1, 2, 3], function(num){ alert(num); });
=> alerts each number in turn...
Эндрю Томсон
источник
7
Для новых исследователей этого вопроса я просто хотел бы указать на Lo-Dash , духовного преемника Underscore, который во многом улучшил его.
Марк Рид
3
Зачем использовать, underscoreесли ECMA-262 был добавлен forEachметор. Родной код всегда лучше.
Уолтер Чапилликен - WZVanG
27

Цикл массива:

for(var i = 0; i < things.length; i++){
    var thing = things[i];
    console.log(thing);
}

Объектный цикл:

for(var prop in obj){
    var propValue = obj[prop];
    console.log(propValue);
}
bzim
источник
27

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

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

Это решения:

1) для цикла

forЦикл не является обычным способом циклический массивами в JavaScript, но не рассматриваются в качестве самых быстрых решений для больших массивов:

for (var i=0, l=arr.length; i<l; i++) {
  console.log(arr[i]);
}

2) Пока цикл

Цикл while считается самым быстрым способом обхода длинных массивов, но обычно он меньше используется в коде JavaScript:

let i=0;

while (arr.length>i) {
    console.log(arr[i]);
    i++;
}

3) Делайте, пока
A do whileделает то же самое, что и whileс некоторой разницей в синтаксисе, как показано ниже:

let i=0;
do {
  console.log(arr[i]);
  i++;
}
while (arr.length>i);

Это основные способы создания циклов JavaScript, но есть еще несколько способов сделать это.

Также мы используем for inцикл для зацикливания объектов в JavaScript.

Также обратите внимание на map(), filter(), reduce()функций и т.д. на массив в JavaScript. Они могут делать вещи намного быстрее и лучше, чем использовать whileи for.

Это хорошая статья, если вы хотите больше узнать об асинхронных функциях над массивами в JavaScript.

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

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

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

Это также означает, что вам больше никогда не придется писать цикл for.

Читать дальше >> здесь :

Алиреза
источник
Есть ли разница в производительности перед циклом for и циклом while при итерации по массиву? У меня сложилось впечатление, что различия были в основном синтаксическими
ши
24

Если кого-то интересует производительность нескольких механизмов, доступных для итераций Array, я подготовил следующие тесты JSPerf:

https://jsperf.com/fastest-array-iterator

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

Результаты:

Традиционный for()итератор, безусловно, является самым быстрым методом, особенно при использовании с кэшированной длиной массива .

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

for(let i=0, size=arr.length; i<size; i++){
    // Do something
}

Array.prototype.forEach()И Array.prototype.map()методы являются самыми медленными приближениями, вероятно , как следствие накладных расходов вызова функции .

colxi
источник
лучше использовать i = i +1вместоi++
DarckBlezzer
2
Может быть улучшено: Пожалуйста, используйте: ++ i вместо i ++, это позволит избежать временного объекта. Таким образом, это уменьшает использование памяти и процессорного времени (выделение не требуется)!
PowerStat
@PowerStat Можете ли вы предоставить ссылку или ссылку на это? Я никогда не слышал об этом, звучит интересно ...
Colxi
1
@colxi Для таких интересных вещей вы должны прочитать хардкорный материал C ++ от Херба Саттера и Скотта Мейерса. Информация о ++ i и i ++ взята из книги: «Исключительный C ++: 47 инженерных головоломок, проблем программирования и решений». Я думаю, вы также можете найти это на gotw.ca, но это может быть доказано для любого языка программирования.
PowerStat
21

Если вы используете библиотеку jQuery, рассмотрите возможность использования http://api.jquery.com/jQuery.each/

Из документации:

jQuery.each( collection, callback(indexInArray, valueOfElement) )

Возвращает: Объект

Описание: универсальная функция итератора, которую можно использовать для бесшовной итерации как по объектам, так и по массивам. Массивы и массоподобные объекты со свойством длины (например, объект аргументов функции) итерируются по числовому индексу от 0 до длины-1. Другие объекты повторяются через их именованные свойства.

Эта $.each()функция отличается от функции $(selector).each(), используемой исключительно для итерации объекта jQuery. $.each() Функция может быть использована для перебора любой коллекции, будь то карта (объект JavaScript) или массив. В случае массива обратному вызову каждый раз передается индекс массива и соответствующее значение массива. (К значению также можно получить доступ через thisключевое слово, но Javascript всегда будет переносить thisзначение как Objectчетное, даже если это простая строка или числовое значение.) Метод возвращает свой первый аргумент - объект, который был повторен.

justingordon
источник
9
JQuery для всего?
Исключение
6
Согласился с исключением. Не стоит недооценивать влияние дополнительных зависимостей. Я бы посоветовал против этого, за исключением кода, который в любом случае уже активно использует jQuery.
Стейн де Витт
2
Обновление: в наши дни вы можете использовать Array.forEach, чтобы получить почти такой же эффект с нативными массивами.
Стейн де Витт
21

Я еще не видел этот вариант, который лично мне нравится больше всего:

Учитывая массив:

var someArray = ["some", "example", "array"];

Вы можете зациклить его, даже не обращаясь к свойству длины:

for (var i=0, item; item=someArray[i]; i++) {
  // item is "some", then "example", then "array"
  // i is the index of item in the array
  alert("someArray[" + i + "]: " + item);
}

Посмотрите это JsFiddle, демонстрирующее, что: http://jsfiddle.net/prvzk/

Это работает только для массивов, которые не разрежены. Это означает, что в каждом индексе массива есть значение. Однако я обнаружил, что на практике я редко использую разреженные массивы в JavaScript ... В таких случаях обычно гораздо проще использовать объект в качестве карты / хеш-таблицы. Если у вас есть разреженный массив, и вы хотите зациклить 0 .. length-1, вам нужна конструкция for (var i = 0; i <someArray.length; ++ i), но вам все еще нуженif внутренний цикл проверить, действительно ли определен элемент в текущем индексе.

Кроме того, как CMS упоминает в комментарии ниже, вы можете использовать это только для массивов, которые не содержат ложных значений. Массив строк из примера работает, но если у вас есть пустые строки или числа, которые равны 0 или NaN, и т. Д., Цикл преждевременно оборвется. Опять же, на практике это вряд ли проблема для меня, но это то, что нужно иметь в виду, что заставляет задуматься об этом, прежде чем использовать его ... Это может дисквалифицировать его для некоторых людей :)

Что мне нравится в этом цикле:

  • Это коротко, чтобы написать
  • Нет необходимости обращаться (не говоря уже о кеше) к свойству length
  • Элемент для доступа автоматически определяется в теле цикла под выбранным вами именем.
  • Очень естественно сочетается с array.push и array.splice для использования массивов, таких как списки / стеки

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

Для меня эта конструкция наиболее близко имитирует синтаксис Java 5, который мне нравится:

for (String item : someArray) {
}

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

Стейн де Витт
источник
14
Обратите внимание , что при таком подходе цикл остановится , как только он находит значение falsey , такие как пустая строка, 0, false, NaN, nullили undefined, еще до того, iдостигает длины, например: jsfiddle.net/prvzk/1
CMS
3
Условие цикла может быть (item=someArray[i]) !== undefined.
daniel1426
18

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

for (var i in array) if (array.hasOwnProperty(i)) {
    // Do something with array[i]
}

но он все равно будет перебирать пользовательские свойства.

В JavaScript любое пользовательское свойство может быть назначено любому объекту, включая массив.

Если один хочет перебрать разреженный массив, for (var i = 0; i < array.length; i++) if (i in array)или array.forEachс es5shimдолжно быть использован.

kirilloid
источник
А как насчет использования for (var i in array) if (++i)?
Даниэль Соколовский
15

Есть несколько способов сделать это в JavaScript. Первые два примера являются примерами JavaScript. Третий использует библиотеку JavaScript, то есть jQuery использует .each()функцию.

var myStringArray = ["hello", "World"];
for(var i in myStringArray) {
  alert(myStringArray[i]);
}

var myStringArray = ["hello", "World"];
for (var i=0; i < myStringArray.length; i++) {
  alert(myStringArray[i]);
}

var myStringArray = ["hello", "World"];
$.each(myStringArray, function(index, value){
  alert(value);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Шубхам Хатри
источник
for...inследует избегать для объектов, подобных массиву
brk
15

Самый элегантный и быстрый способ

var arr = [1, 2, 3, 1023, 1024];
for (var value; value = arr.pop();) {
    value + 1
}

http://jsperf.com/native-loop-performance/8


Отредактировано (потому что я был неправ)


Сравнение методов для циклического прохождения массива из 100000 элементов и выполнения минимальной операции с новым значением каждый раз.

Приготовление:

<script src="//code.jquery.com/jquery-2.1.0.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<script>
    Benchmark.prototype.setup = function() {
        // Fake function with minimal action on the value
        var tmp = 0;
        var process = function(value) {
            tmp = value; // Hold a reference to the variable (prevent engine optimisation?)
        };

        // Declare the test Array
        var arr = [];
        for (var i = 0; i < 100000; i++)
            arr[i] = i;
    };
</script>

тесты:

<a href="http://jsperf.com/native-loop-performance/16" 
   title="http://jsperf.com/native-loop-performance/16"
><img src="http://i.imgur.com/YTrO68E.png" title="Hosted by imgur.com" /></a>
molokoloco
источник
Этот цикл не соответствует порядку элементов в массиве.
Дениз Озгер
Мой тест был неверным. Это правильно, показывая все петли сейчас. jsperf.com/native-loop-performance/16
molokoloco
@bergi прав. Этот цикл стирает массив, когда он проходит через него. Не то, что вы хотите в большинстве случаев.
Стейн де Витт
4
перерывы на фальшивые предметы.
njzk2
12

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

var i, max, myStringArray = ["Hello","World"];
for (i = 0, max = myStringArray.length; i < max; i++) {
    alert(myStringArray[i]);
   //Do something
}

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

var i,myStringArray = ["item1","item2"];
for (i =  myStringArray.length; i--) {
    alert(myStringArray[i]);
}

или лучше и чище использовать цикл while:

var myStringArray = ["item1","item2"],i = myStringArray.length;
while(i--) {
   // do something with fruits[i]
}
Захир Ахмед
источник
12

В JavaScript существует очень много решений для создания цикла.

Код ниже популярные

/** Declare inputs */
const items = ['Hello', 'World']

/** Solution 1. Simple for */
console.log('solution 1. simple for')

for (let i = 0; i < items.length; i++) {
  console.log(items[i])
}

console.log()
console.log()

/** Solution 2. Simple while */
console.log('solution 2. simple while')

let i = 0
while (i < items.length) {
  console.log(items[i++])
}

console.log()
console.log()

/** Solution 3. forEach*/
console.log('solution 3. forEach')

items.forEach(item => {
  console.log(item)
})

console.log()
console.log()

/** Solution 4. for-of*/
console.log('solution 4. for-of')

for (const item of items) {
  console.log(item)
}

console.log()
console.log()

Алонгкорн Четасумон
источник
12

Если вы хотите использовать jQuery, в его документации есть хороший пример:

 $.each([ 52, 97 ], function( index, value ) {
      alert( index + ": " + value );
 });
jj_
источник
12

На мой взгляд, лучший способ - использовать функцию Array.forEach. Если вы не можете использовать это, я бы предложил получить полифилл из MDN. Чтобы сделать его доступным, это, безусловно, самый безопасный способ перебора массива в JavaScript.

Array.prototype.forEach ()

Итак, как и предполагали другие, это почти всегда то, что вы хотите:

var numbers = [1,11,22,33,44,55,66,77,88,99,111];
var sum = 0;
numbers.forEach(function(n){
  sum += n;
});

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

Используя обычный стиль C for цикла в работает в большинстве случаев. Просто важно помнить, что все внутри цикла разделяет свою область с остальной частью вашей программы, {} не создает новую область.

Следовательно:

var sum = 0;
var numbers = [1,11,22,33,44,55,66,77,88,99,111];

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

alert(i);

выдаст «11» - что может или не может быть то, что вы хотите.

Рабочий пример jsFiddle: https://jsfiddle.net/workingClassHacker/pxpv2dh5/7/

Эспен
источник
10

Это не на 100% идентично, но похоже:

   var myStringArray = ['Hello', 'World']; // array uses [] not {}
    for (var i in myStringArray) {
        console.log(i + ' -> ' + myStringArray[i]); // i is the index/key, not the item
    }

Мухаммед Элвин
источник
1
Кажется, что это столкнулось бы с подобными проблемами, как и в случае использования с объектом массива, в этом случае переменные-члены прототипа также были бы перехвачены в for.
Kzqai
9

Например, я использовал в консоли Firefox:

[].forEach.call(document.getElementsByTagName('pre'), function(e){ 
   console.log(e);
})
victorq10
источник
9
var x = [4, 5, 6];
for (i = 0, j = x[i]; i < x.length; j = x[++i]) {
    console.log(i,j);
}

Намного чище ...

staticd
источник
Это не очень чисто по сравнению с z.forEach(j => console.log(j));.
Sapphire_Brick
9

Краткий ответ: да. Вы можете сделать с этим:

var myArray = ["element1", "element2", "element3", "element4"];

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

В консоли браузера вы можете увидеть что-то вроде «element1», «element2» и т. Д. Напечатано.

Хуанхо Сальвадор
источник
9

Вы можете использовать Array.prototype.forEach(...):

var arr = ["apple", "banana", "cherry", "mango"];
arr.forEach((item, index)=>{
   //Some code...
});

Или Array.prototype.map(...):

var arr = ["apple", "banana", "cherry", "mango"];
arr.map((item, index)=>{
   //Some code...
});

Или jquery или для циклических способов, упомянутых ранее.

Sapphire_Brick
источник