Если вы пишете JavaScript даже в течение короткого промежутка времени,
вы, вероятно, все еще знаете, как быстро меняется язык. Учитывая все эти
изменения, это означает, что существует несколько способов выполнения
одной и той же функции. В этом случае я имею в виду цикл по массивам с
использованием конструкции for-each
.
Итак, как лучше всего это сделать? Этот вопрос зависит от нескольких вещей, например, какую версию JS вы используете, можете ли вы использовать методы экземпляра и т. Д. В этой статье я исследую несколько способов перебора массивов в JS.
Метод массива forEach
Широко поддерживаемым методом (за исключением IE 8, что неудивительно)
является метод Array.prototype.forEach
Он работает, принимая функцию
обратного вызова с параметрами currentValue
, index
и array
. Во
многих случаях используются только параметры currentValue
и index
.
Вот пример:
let items = ['one', 'two', 'three', 'four'];
items.forEach(function(val, idx) {
console.log(`${idx}: ${val}`);
});
// Output:
//
// 0: one
// 1: two
// 2: three
// 3: four
Это отличный метод благодаря своей простоте и чистому синтаксису, хотя у
него есть некоторые недостатки. В частности, трудно выйти из этого
цикла, в отличие от встроенного for
где вы можете использовать
ключевое слово break
С forEach
вы должны выбросить исключение, чтобы
выйти из цикла раньше.
Как указано в документации
MDN
, если вам нужно выйти из forEach
, то этот метод - неправильный
инструмент. В этом случае лучшими вариантами будут:
- Встроенный
for
(подробно описан ниже) - Встроенный
for-of
(подробно описан ниже) Array.prototype.every()
Array.prototype.some()
Array.prototype.find()
Array.prototype.findIndex()
Array.prototype.*
Могут выходить из своих циклов, возвращая истинное
значение, которое сообщает циклу, следует ли ему продолжить.
Метод forEach
хорош, когда у вас есть очень простые требования к
циклу, и вам не нужен большой контроль над фактическим поведением цикла.
Однако за эту простоту приходится платить. Это примерно на 95%
медленнее, чем встроенный for
, но для большинства людей это
замедление будет незначительным.
Встроенный цикл
Встроенный for
(также известный как простой for
), вероятно,
является наиболее известным из вариантов, поскольку он работает в
JavaScript так же, как и во многих других языках. Синтаксис следующий:
let items = ['one', 'two', 'three', 'four'];
for (let i = 0; i < items.length; ++i) {
console.log(`${i}: ${items[i]}`);
}
// Output:
//
// 0: one
// 1: two
// 2: three
// 3: four
Такой for
имеет ряд преимуществ:
- Это знакомо большинству программистов
- Ключевые слова продолжения цикла управления
break
иcontinue
- Контролировать направление счетчика (через
++i
или--i
) и скорость (т.е.i+2
) - Частичный цикл (т.е.
for (let i = 0; i < items.length/2; ++i)
)
Имея такой большой контроль над вашим циклом, вам также придется иметь дело с его подробным синтаксисом, поэтому его часто избегают для более простых случаев использования.
Обратите внимание, что в приведенном выше примере предполагается, что вы
используете ES6 JavaScript, в противном случае вам нужно будет объявить
i
с помощью var
и вне самого цикла.
Встроенный цикл for-in
Вероятно, наиболее часто неправильно понимаемая форма цикла в JavaScript
- это цикл
for-in
На первый взгляд кажется, что вы можете использовать это для циклического перебора каждого индекса в массиве, но на самом деле он предназначен для перебора имен перечислимых свойств объекта, а не обязательно только индексов.
Например, вот как он используется с массивами:
let items = ['one', 'two', 'three', 'four'];
for (let i in items) {
console.log(`${i}: ${items[i]}`);
}
// Output:
//
// 0: one
// 1: two
// 2: three
// 3: four
И вот как он предназначен для использования с объектами:
let obj = {hi: 'bye', one: 'two', foo: 'bar'};
for (let o in obj) {
console.log(`${o}: ${obj[o]}`);
}
// Output
//
// hi: bye
// one: two
// foo: bar
Многие разработчики явно не рекомендуют использовать это для перебора массивов, особенно если порядок важен, поскольку порядок не гарантируется.
Если вы хотите перебрать массив с таким синтаксисом, for-of
, что
является предметом рассмотрения в следующем разделе.
Встроенный цикл for-of
for-of
имеют синтаксис, очень похожий на синтаксис for-in
, который
мы только что видели. Однако их главное отличие состоит в том, что он
выполняет итерацию по итерируемым объектам (таким как строки, массивы,
карты, наборы и т. Д.), Тогда как for-in
выполняет итерацию по всем
перечислимым свойствам объекта, не являющимся символом.
На практике это выглядит так:
let items = ['one', 'two', 'three', 'four'];
for (let i of items) {
console.log(i);
}
// Output:
//
// one
// two
// three
// four
Обратите внимание, что i
больше не является индексом, а представляет
собой фактическое значение массива. И поскольку он работает только с
итерациями, мы больше не можем использовать объект:
let obj = {hi: 'bye', one: 'two', foo: 'bar'};
for (let o of obj) {
console.log(o);
}
// Output:
//
// TypeError: obj is not iterable
С точки зрения синтаксиса и функциональности это своего рода компромисс
между Array.forEach
и встроенным for
поскольку синтаксис чище, чем
простой for
, и он по-прежнему позволяет использовать ключевые слова
"управления" циклом, такие как break
и continue
, в отличие от
forEach
.
Еще одна приятная особенность заключается в том, что он хорошо работает с генераторами , поэтому вы можете легко использовать это в своих циклах:
function* myWords() {
yield 'foo';
yield 'bar';
yield 'baz';
}
for (let w of myWords()) {
console.log(w);
}
// Output:
//
// foo
// bar
// baz
Заключение
Как видите, существует довольно много способов выполнить цикл for-each над массивом в JavaScript, и выбранная вами конструкция во многом зависит от того, чего вы хотите достичь, и от вашего конкретного варианта использования.
В этой статье мы увидели, как перебирать массивы с помощью
Array.forEach
, встроенных циклов for
for-in
и for-of
. Не
стесняйтесь оставлять комментарии ниже с любыми критическими замечаниями
или улучшениями, которые вы видите.