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

avatar
Mark Szymanski
10 июня 2010 в 00:04
4332491
44
3557

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

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

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

Источник
Mark Szymanski
10 июня 2010 в 00:15
5

Хорошо, я немного запутался, можно ли использовать расширенный цикл for при доступе к объектам? А использовать для заполнения последовательную? Это верно?

Christian C. Salvadó
10 июня 2010 в 00:38
49

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

jondavidjohn
1 ноября 2011 в 17:53
4

связанные - coderhelper.com/questions/5349425/…

alex
18 декабря 2015 в 10:09
0

связанные - coderhelper.com/q/6208964/31671

Hamed Mahmoudkhani
8 октября 2016 в 12:17
0

Также: myStringArray.forEach(function(value, index){ console.log(index, value) }); и результат будет 0 "Hello" 1 "World"

EscapeNetscape
3 ноября 2016 в 19:45
7

jsben.ch/#/Q9oD5 <= Вот эталон набора решений для циклического перебора массивов

Roobie Nuby
29 августа 2018 в 00:53
1

@EscapeNetscape ссылка изменилась и теперь имеет вид jsben.ch/Q9oD5. Подводя итог, последовательный цикл for занимает 60% времени, которое занимает for-in.

jpmc26
5 октября 2018 в 15:59
6

@CMS Нет, это не совсем просто. Это действительно просто на любом другом языке. Это до смешного сложно в JS, где у вас есть in и of, которые можно использовать и делать разные вещи. Кроме того, у вас также есть forEach и уродливый и раздражающий цикл на основе индекса. Любой другой современный язык делает цикл по коллекции простым и понятным, без сюрпризов или путаницы. JS тоже мог бы, но это не так.

Aryan Beezadhur
7 января 2021 в 11:31
0

Отвечает ли это на ваш вопрос? Для каждого по массиву в JavaScript

Ответы (44)

avatar
Alfredo Rahn Linde
10 ноября 2021 в 03:48
0

Подумайте об этом:

var ITEMS = ['Один','Два','Три'] var item=-1

Затем вы получаете зацикливание при каждом вызове:

ЭЛЕМЕНТЫ[item=item==ITEMS.length-1?0:item+1]

avatar
Aleksandr Golovatyi
15 июня 2021 в 14:03
16

Есть 4 способа итерации массива:

// 1: for

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

// 2: forEach

arr.forEach((v, i) => console.log(v));

// 3: for in

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

// 4: for of

for (const v of arr) {
  console.log(v);
}

Резюме : решения 1 и 3 создают дополнительную переменную, 2 - создают дополнительный контекст функции. Лучше всего 4-й вариант - «за из» .

YesItsMe
3 августа 2021 в 02:04
1

Не могли бы вы объяснить, почему 4 "за из" лучше остальных

Aleksandr Golovatyi
3 августа 2021 в 09:39
0

Он не создает ненужных переменных или функционального контекста. Но если вас не волнуют мелкие недостатки, вы можете использовать любой из них, какой вам удобнее. @YesItsMe Спасибо за вопрос.

avatar
Satish Chandra Gupta
5 июня 2021 в 06:21
19

6 различных методов обхода массива

Вы можете перебирать массив множеством различных методов. Я отсортировал свои 6 любимых методов сверху вниз.

1. Использование для цикла

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

let array = [1, 2, 3, 4, 5];
for (let i = 0; i < array.length; i++) {
  console.log(array[i]);
}

2. Использование цикла forEach

forEach Цикл - это современный способ циклического перебора массива. Кроме того, это дает большую гибкость и контроль над массивом и элементами.

let array = [1, 2, 3, 4, 5];
array.forEach((element) => {
  console.log(element);
});

3. Использование для ... из

for...of Цикл дает вам прямой доступ к элементам массива.

let array = [1, 2, 3, 4, 5];
for (let element of array) {
  console.log(element);
}

4. Использование for ... в цикле

for...in дает вам ключ, с помощью которого вы можете получить доступ к элементам массива.

let array = [1, 2, 3, 4, 5];
for(let index in array){
  console.log(array[index]);
}

5. Использование цикла while

while loop можно также использовать для циклического просмотра массива.

let array = [1, 2, 3, 4, 5];
let length = array.length;
while(length > 0){
  console.log(array[array.length - length]);
  length--;
}

6. Использование цикла do ... while

Точно так же я использую do...while цикл

let array = [1, 2, 3, 4, 5];
let length = array.length;
do {
  console.log(array[array.length - length]);
  length--;
}
while (length > 0)
avatar
TheComputerWizard
28 ноября 2020 в 00:05
9
//Make array
var array = ["1","2","3","4","5","6","7","8","9","10"]
//Loop
for(var i = 0; i < array.length; i++){
 console.log((i+1) + " --> " + array[i])
}

Для ФАКТИЧЕСКОГО числа для i вам нужно изменить (i+1) на i или (i), если хотите.
Надеюсь, это помогло.

avatar
kabirbaidhya
21 сентября 2020 в 15:42
4

Шпаргалка по обходу массива в JavaScript

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

1. Классический for петля

const myArray = ['Hello', 'World'];

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

2. for...of

const myArray = ['Hello', 'World'];

for (const item of myArray) {
  console.log(item);
}

3. Array.prototype.forEach()

const myArray = ['Hello', 'World'];

myArray.forEach(item => {
  console.log(item);
});

4. while петля

const myArray = ['Hello', 'World'];
let i = 0;

while (i < myArray.length) {
  console.log(myArray[i]);
  i++;
}

5. do...while петля

const myArray = ['Hello', 'World'];
let i = 0;

do {
  console.log(myArray[i]);
  i++;
} while (i < myArray.length);

6. Стиль очереди

const myArray = ['Hello', 'World'];


while (myArray.length) {
  console.log(myArray.shift());
}

7. Стиль стека

Примечание: В этом списке список напечатан на обратной стороне.

const myArray = ['Hello', 'World'];

while (myArray.length) {
  console.log(myArray.pop());
}
Aleksandr Golovatyi
17 июня 2021 в 07:43
0

Циклы for и for in создают дополнительную переменную, forEach - создают дополнительный контекст функции. Думаю, лучший способ - «за из».

avatar
Kamil Kiełczewski
19 декабря 2019 в 06:40
19

Эзотерический изменчивый путь

let a= ["Hello", "World"];

while(a.length) { console.log( a.shift() ); }
Sapphire_Brick
16 января 2020 в 02:49
0

это способ сделать это в стиле Haskell; продолжай принимать первый. умно, но, вероятно, медленно.

Kamil Kiełczewski
24 июля 2020 в 10:06
0

@Sapphire_Brick на самом деле довольно быстро - вот тест

Sapphire_Brick
24 июля 2020 в 21:24
0

Конечно, такая простая программа работает быстро, но как она масштабируется по сравнению с for(...;...;...) или for(... of ...)?

Kamil Kiełczewski
24 июля 2020 в 22:04
0

@Sapphire_Brick не ленитесь! :) Вы можете проверить это самостоятельно - я даю вам ссылку (тест) на инструмент в комментарии выше. Однако для случая небольшого массива (как использует OP), когда вам нужно оптимизировать скорость, вы должны выбрать самое быстрое решение для небольших массивов (не для больших массивов - которые могут быть разными)

Sapphire_Brick
4 августа 2020 в 20:51
4

Вы правильно подметили. Я запустил ваш пример с массивом из 1000 элементов, и while(a.length) { console.log(a.shift()); } был примерно в два раза быстрее, чем версия for(var i = 0; i < a.length; i++) { console.log(a[i]); }. ¯ \ _ (ツ) _ / ¯

Kamil Kiełczewski
4 августа 2020 в 21:23
0

@Sapphire_Brick - спасибо за ваш комментарий - я считаю, что использование console.log в тестах не очень хорошо, потому что это сложная системная функция и имеет большое влияние на время выполнения. Я проверяю r+=a[i].length (сумма длины слов) для массива с 1000 элементами - и все же это решение было намного быстрее, чем другое решение (и, возможно, разница в скорости растет, когда количество элементов растет ...) - Я тоже удивлен что это решение такое быстрое :)

Peter Mortensen
30 октября 2020 в 08:35
3

Даже если его нет на вашем родном языке, вы не должны пропускать статьи на английском языке (неопределенный артикль («a» или «an») и определенный артикль («the»)). См., Например, Статьи на английском языке - 3 простых правила для исправления типичных грамматических ошибок и ошибок и A, AN, THE - Статьи на английском языке <1409993664866> <14093

Arthur S
9 ноября 2020 в 20:03
0

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

Pitouli
1 марта 2021 в 03:52
0

Осторожный! Тест неверен, потому что массив не сбрасывается между каждым выполнением. Поскольку shift () опустошил массив после первого выполнения, все последующие выполнения действительно выполняются очень быстро: p Если вы правильно сбросили массив, оказывается, что это решение является вторым по скорости. jsbench.me/4dklq1kjef/1

Kamil Kiełczewski
1 марта 2021 в 05:21
2

@Pitouli ты прав - откатываю ответ к исходному виду. Когда у меня будет больше времени, я снова проведу тесты

avatar
Sapphire_Brick
15 августа 2019 в 00:50
10

Формальный (и, возможно, старый) способ: Array.prototype.forEach(...):

var arr = ["apple", "banana", "cherry", "mango"];
arr.forEach(function(item, index, _) {
   console.log("[" + index + "] = '" + item + "'");
});
John Lord
23 октября 2020 в 16:17
0

в вашем «некотором коде» должен быть пример. Не совсем ясно, передаются ли переменные напрямую или как «это» или что-то еще.

avatar
Shijo Rs
9 октября 2018 в 13:17
3

var array = ['hai', 'hello', 'how', 'are', 'you']
$(document).ready(function () {
  $('#clickButton').click(function () {
    for (var i = 0; i < array.length; i++) {
      alert(array[i])
    }
  })
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<input id="clickButton" value="click Me" type="button"/>
<div id="show"></div>
domdambrogia
5 марта 2019 в 22:46
4

Было ли действительно необходимо использовать здесь jQuery или HTML?

Peter Mortensen
30 октября 2020 в 08:28
0

@domdambrogia: Это мем.

avatar
colxi
20 августа 2018 в 23:36
24

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

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

Performance results

Результаты:

Традиционный итератор 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() - самые медленные приближения, вероятно, из-за накладных расходов на вызов функции .

DarckBlezzer
10 декабря 2018 в 18:19
0

лучше использовать i = i +1 вместо i++

PowerStat
17 мая 2019 в 10:05
2

Можно улучшить: используйте: ++ i вместо i ++, это позволит избежать временного объекта. Таким образом, сокращается использование памяти и время процессора (выделение не требуется)!

colxi
17 мая 2019 в 13:23
0

@PowerStat, можете ли вы дать ссылку или справку по этому поводу? Я никогда об этом не слышал, звучит интересно ...

PowerStat
17 мая 2019 в 17:44
1

@colxi Для таких интересных вещей вы должны прочитать хардкорные материалы по C ++ от Херба Саттера и Скотта Мейерса. Тема ++ i vs i ++ взята из книги: Exceptional C ++: 47 Engineering Puzzles, Programming Problems, and Solutions - я думаю, вы также можете найти это на gotw.ca, но это может быть доказано для любого языка программирования .

avatar
Yuci
23 февраля 2018 в 11:29
38

Некоторые варианты использования цикла по массиву в способе функционального программирования в 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);

enter image description here

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

enter image description here

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

Ссылки

avatar
BILAL AHMAD
13 сентября 2017 в 22:11
7

Простое однострочное решение:

arr = ["table", "chair"];

// Solution
arr.map((e) => {
  console.log(e);
  return e;
});
Michel Jung
6 октября 2017 в 11:09
4

Вы бы предпочли использовать .forEach() и отбросить return e;

marpme
17 ноября 2017 в 22:28
3

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

avatar
Andrew
2 сентября 2017 в 20:35
7

Похоже, что были перечислены все варианты, кроме forEach по lodash:

_.forEach([1, 2], (value) => {
  console.log(value);
});
avatar
Alireza
27 мая 2017 в 02:57
36

Да, , вы можете сделать то же самое в 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

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

let i=0;

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

3) Выполнить, пока
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.

Подробнее >> здесь:

avatar
Espen
26 октября 2016 в 08:51
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/

avatar
Alongkorn
14 октября 2016 в 10:31
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()
avatar
bzim
1 августа 2016 в 21:18
29

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

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);
}
avatar
Dan Chill
26 мая 2016 в 19:11
5
var obj = ["one","two","three"];

for(x in obj){
    console.log(obj[x]);
}
avatar
Amit Jamwal
29 апреля 2016 в 09:05
9
var myStringArray = ["hello", "World"];
myStringArray.forEach(function(val, index){
   console.log(val, index);
})
avatar
Shubham Khatri
21 апреля 2016 в 16:03
14

Есть несколько способов сделать это в 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>
brk
5 декабря 2016 в 05:25
0

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

avatar
user6139250
31 марта 2016 в 11:28
4

Лучше использовать последовательный for цикл:

for (var i = 0; i < myStringArray.length; i++) {
    // Do something
}
Sapphire_Brick
27 сентября 2019 в 18:55
2

Почему лучше? конечно, вы можете сделать это и в java, но он спросил о цикле foreach .

avatar
jj_
30 марта 2016 в 02:37
12

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

 $.each([ 52, 97 ], function( index, value ) {
      alert( index + ": " + value );
 });
avatar
Juanjo Salvador
17 марта 2016 в 10:13
9

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

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

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

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

avatar
John Slegers
29 февраля 2016 в 18:56
82

Введение

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

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


Традиционный for -цикл

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

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

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

for (;;) {
    // Do stuff
}

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

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

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

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

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


A 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...of14> <401439> .40724072>. В следующем примере показана разница между циклом 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() , в <40147340721472>:

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

_.each() , в Underscore.js <407214623>14

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

_.forEach() , в Лодаш :

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

avatar
Daniel K.
12 декабря 2015 в 03:11
8

Конечно, это неэффективно, и многие презирают его, но он один из самых близких к упомянутому:

var myStringArray = ["Hello","World"];
myStringArray.forEach(function(f){
    // Do something
})
user513951
12 декабря 2015 в 03:27
3

Эта точная функциональность уже является частью ответа Марка Рида.

avatar
victorq10
21 октября 2014 в 07:32
9

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

[].forEach.call(document.getElementsByTagName('pre'), function(e){ 
   console.log(e);
})

Вы можете использовать querySelectorAll, чтобы получить тот же результат

document.querySelectorAll('pre').forEach( (e) => { 
   console.log(e.textContent);
})
<pre>text 1</pre>
<pre>text 2</pre>
<pre>text 3</pre>
avatar
RizN81
23 июля 2014 в 12:59
29

В 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 check jQuery для каждого <416654.

>
avatar
Sambhav Sharma
9 мая 2014 в 14:21
6

А как насчет этого:

for (var key in myStringArray) {
    console.log(myStringArray[key]);
}
Matt
9 мая 2014 в 14:25
10

Циклы for / in не рекомендуются для перечисления массивов, поскольку порядок перечисления не гарантируется, и он перечисляет свойства, а не только элементы массива. Для получения дополнительной информации см. coderhelper.com/questions/500504/… или даже принятый ответ на этот вопрос; coderhelper.com/a/3010848/444991

Sambhav Sharma
9 мая 2014 в 14:32
0

ну спасибо за обновление .. а что насчет ситуации, когда нас не волнует порядок массива? Будет ли это по-прежнему обескуражено?

Matt
9 мая 2014 в 14:35
4

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

avatar
molokoloco
8 марта 2014 в 02:06
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>
Deniz Ozger
26 марта 2014 в 15:36
0

Этот цикл, похоже, не соответствует порядку элементов в массиве.

molokoloco
27 марта 2014 в 16:41
0

Мой тест был неправильным. Правильно, сейчас показаны все ПЕТЛИ. jsperf.com/native-loop-performance/16

Stijn de Witt
15 мая 2014 в 17:34
0

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

njzk2
29 июля 2014 в 14:59
4

ломается по фальшивым предметам.

avatar
Zaheer Ahmed
11 января 2014 в 20:53
12

Оптимизированный подход заключается в кэшировании длины массива и использовании шаблона одной переменной, инициализации всех переменных одним ключевым словом 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]
}
avatar
Marlon Bernardes
11 августа 2013 в 15:54
135

для (константы myStringArray) {

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

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

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

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

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

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

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

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

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

for(const 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 (const 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 loops

Спецификация: http://wiki.ecmascript.org/doku.php?id=harmony:iterators

}

avatar
staticd
6 августа 2013 в 08:03
9
var x = [4, 5, 6];
for (i = 0, j = x[i]; i < x.length; j = x[++i]) {
    console.log(i,j);
}

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

Sapphire_Brick
17 марта 2020 в 14:57
0

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

avatar
Stijn de Witt
28 февраля 2013 в 13:59
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, и т. Д. Цикл преждевременно прервется. Опять же на практике это вряд ли когда-либо проблема для меня, но об этом нужно помнить, что заставляет задуматься над этим циклом, прежде чем использовать его ... Это может дисквалифицировать его для некоторых людей :)

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

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

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

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

for (String item : someArray) {
}

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

Christian C. Salvadó
28 февраля 2013 в 18:31
14

Обратите внимание, что при таком подходе цикл остановится, как только он обнаружит ложное значение , такое как пустая строка, 0, false, NaN, null или undefined, даже прежде чем i достигнет длины, например: jsfiddle.net/prvzk/1

daniel1426
20 марта 2014 в 14:17
3

Условие цикла может быть (item=someArray[i]) !== undefined.

avatar
justingordon
21 октября 2012 в 06:20
21

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

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

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

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

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

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

Stijn de Witt
31 марта 2013 в 19:04
6

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

Stijn de Witt
5 июня 2017 в 10:50
2

Обновление: в наши дни вы можете использовать Array.forEach, чтобы получить тот же эффект с собственными массивами.

avatar
Phrogz
4 июня 2012 в 16:26
40

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

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 во время итерации.

Stijn de Witt
1 марта 2013 в 12:09
16

Для людей, которые не понимают столь гениального: сначала вычисляется выражение i--, которое позволяет продолжить цикл, если оно не является ложным ... После этого счетчик уменьшается. Как только i станет равным нулю, он выйдет из цикла, так как ноль является ложным значением в Javascript.

danwellman
27 апреля 2013 в 07:33
5

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

avatar
Muhammad Alvin
18 апреля 2012 в 14:46
11

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

   var myStringArray = ['Hello', 'World']; // The array uses [] not {}
    for (var i in myStringArray) {
        console.log(i + ' -> ' + myStringArray[i]); // i is the index/key, not the item
    }
Kzqai
18 апреля 2012 в 15:34
1

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

avatar
Andrew Thomson
16 апреля 2012 в 23:33
28

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

Например:

_.each([1, 2, 3], function(num){ alert(num); });
=> alerts each number in turn...
Mark Reed
11 октября 2013 в 10:59
7

Для новичков в этом вопросе я просто хотел бы указать на Lo-Dash, духовного преемника Underscore, улучшающего его во многих отношениях.

Walter Chapilliquen - wZVanG
23 июня 2015 в 23:32
3

Зачем использовать underscore, если в ECMA-262 был добавлен метод forEach. Нативный код всегда лучше.

avatar
Mark Reed
16 апреля 2012 в 02:03
1143

Да, если ваша реализация включает функцию 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; 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 работает для других повторяемых типов, которые могут не иметь этого метода), вы можете использовать метод Array # entries, чтобы изменить его на массив пар [индекс, элемент], а затем перебрать его:

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

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

Phrogz
4 июня 2012 в 16:29
22

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

avatar
kirilloid
15 апреля 2012 в 12:50
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.

Daniel Sokolowski
9 октября 2014 в 14:40
0

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

avatar
Timo Huovinen
5 января 2012 в 09:15
69

Используйте 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]);
}

Он регистрирует: «один», «два», «три»

Ссылка: Закрытие Google: как не писать JavaScript

Chris Cooper
16 апреля 2012 в 14:42
21

Первый пример синтаксиса «while» не будет работать, если какой-либо из элементов массива является ложным.

Stijn de Witt
31 марта 2013 в 19:09
2

... и этот цикл while эквивалентен: for (var i = 0, item; item = items [i]; i ++), что избавляет от необходимости заранее объявлять переменные index и item ...

avatar
Gabriel
16 мая 2011 в 22:52
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 и множество других методов в прототипе массива.

.
Phrogz
4 июня 2012 в 16:28
3

Обратите внимание, что некоторые интерпретаторы (например, V8) автоматически кэшируют длину массива, если код вызывается достаточное количество раз и он обнаруживает, что длина не изменяется циклом.

Gabriel
26 июня 2012 в 01:43
0

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

Stijn de Witt
31 марта 2013 в 19:06
1

@ Габриэль: Почему? Приведите реальные примеры, показывающие, что отсутствие кеширования длины на самом деле является узким местом производительности. Я придерживаюсь подхода «преждевременная оптимизация - корень всех зол». Я исправлю тот единственный цикл, который на самом деле представляет проблему, как только я с ним столкнусь ...

Gabriel
4 апреля 2013 в 17:15
1

@StijndeWitt, я думаю, это просто стилистическая проблема. Честно говоря, я больше даже не использую циклы for, вместо этого полагаюсь на подчеркивание для таких вещей, как _.each, _.map и т. Д., Чтобы делать эти вещи. Когда я писал такие циклы, я в первую очередь кешировал длину, чтобы все мои объявления переменных находились в одном месте, в верхней части моей функции. Следование моим советам в этом отношении несущественно для любого реального приложения. Преждевременная оптимизация - это очень плохо, но если оптимизация является результатом стилистических решений, я не думаю, что это действительно имеет значение.

Noz
30 июля 2014 в 18:14
1

@Gabriel Я считаю, что JavaScript уже поддерживает функцию карты для массивов, нет необходимости вводить для этого дополнительную библиотеку.

Stijn de Witt
18 декабря 2015 в 16:35
0

@Noz map только недавно получил широкую поддержку в браузерах ... И, конечно же, подчеркивание предлагает нечто большее. Но я полностью согласен с тем, что, если это возможно и не безосновательно более сложно, использование ванильного JS поверх библиотеки всегда является лучшим вариантом. Зависимости плохие . Старайтесь их избегать.

avatar
sebarmeli
7 декабря 2010 в 07:24
121

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

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

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

avatar
kennebec
10 июня 2010 в 02:43
91

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

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

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

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

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

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

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

map похож на 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;
})();
avatar
hasen
10 июня 2010 в 00:09
446

Вы можете использовать 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;});

И теперь x равен [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.

harto
10 июня 2010 в 00:20
100

Этот конкретный пример, вероятно, лучше реализовать с помощью Array.forEach. map предназначен для создания нового массива.

Christian C. Salvadó
10 июня 2010 в 00:30
21

@hasen, метод Array.prototype.map является частью стандарта ECMAScript 5th Edition, еще не доступен во всех реализациях (например, в IE его нет), также для итерации по массиву, я думаю, что Array.prototype.forEach метод более семантически правильный ... также, пожалуйста, не предлагайте инструкцию for-in, подробнее см. Мой ответ :)

avatar
Christian C. Salvadó
10 июня 2010 в 00:07
4505

Три основных варианта:

  1. for (var i = 0; i < xs.length; i++) { console.log(xs[i]); }
  2. xs.forEach((x, i) => console.log(x));
  3. for (const x of xs) { console.log(x); }

Подробные примеры приведены ниже.


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

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

Плюсы

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

Минусы

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

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

Стрелочные функции также широко используются, если вы не планируете поддерживать старые платформы (например, Internet Explorer 11); ты тоже можешь идти.

Плюсы

  • Очень короткое и емкое.
  • Декларативная

Минусы

  • Невозможно использовать 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);

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

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

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. ES6 for-of инструкция:

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

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

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

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

Плюсы

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

Минусы

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

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

bmaupin
15 июня 2021 в 11:41
1

Я знаю, что этот ответ предшествует async и Promises, но я считаю, что об этом стоит упомянуть в любом разговоре, касающемся современного JavaScript: «forEach не ждет обещаний. Убедитесь, что вы знаете о последствиях при использовании обещаний (или асинхронных функций) как forEach обратный вызов ". (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…)

Vic
9 сентября 2021 в 01:13
0

con es6 for-of: невозможно получить текущий индекс