Если вы пишете 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 . Не
стесняйтесь оставлять комментарии ниже с любыми критическими замечаниями
или улучшениями, которые вы видите.