Цикл через массив в JavaScript

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

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

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

Ответ 1

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

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

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

Ответ 2

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

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

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

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

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

Примечание о разреженных массивах: массив в 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 в условие цикла) может существенно myStringArray.length на производительность, поскольку оно пропускает поиск свойств каждый раз до конца; при использовании Rhino на моей машине ускорение составляет 43%.

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

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

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

Ответ 3

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

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

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.

Ответ 4

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

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

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

Ответ 5

для (var s myStringArray) {

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

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

Этот новый синтаксис - самый изящный способ перебора массива в javascript (так как вам не нужен индекс итерации), но он пока еще не поддерживается браузерами.

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

Он также работает на Node (я тестировал его на версии 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/ # Для петель

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

}

Ответ 6

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

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

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

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

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

some возвращает true, если кто-либо передает тест.

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

Ответ 7

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

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

logs: 'one', 'two', 'three'

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

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

logs: 'three', 'two', 'one'

Или классический цикл for

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

logs: 'one', 'two', 'three'

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

Ответ 8

вступление

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

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


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

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

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

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

for (;;) {
    // Do stuff
}

Конечно, вам нужно будет включить if(condition === true) { break; } if(condition === true) { break; } или if(condition === true) { return; } 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...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 и более поздними Array.prototype.forEach().


Библиотеки

Наконец, многие библиотеки утилиты также имеют свои собственные изменения 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);
});

Ответ 9

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

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)), в то время как количество символов меньше.

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

Ответ 10

Некоторые случаи использования циклического перебора массива функциональным способом программирования в 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() возвращает значение первого элемента в массиве, которое удовлетворяет предоставленной функции тестирования.

Рекомендации

Ответ 11

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

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 и множество других методов в Array prototype.

Ответ 12

Существует несколько способов циклического преобразования массива в 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 для каждого.

Ответ 13

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

Например:

_.each([1, 2, 3], function(num){ alert(num); });
=> alerts each number in turn...

Ответ 14

Контур массива:

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

Ответ 15

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

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

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

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

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

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

Ответ 16

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

Ответ 17

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

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

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

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

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

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

Ответ 18

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

Дан массив:

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 & lt; someArray.length; ++i), но вам все еще нужен if внутри цикла, чтобы проверить, действительно ли определен элемент в текущем индексе.

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

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

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

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

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

for (String item : someArray) {
}

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

Ответ 19

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

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.

Ответ 20

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

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>

Ответ 21

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

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

Ответ 22

В 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()

Ответ 23

Оптимизированный подход заключается в кэшировании длины массива и использовании одиночного шаблона 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]
}

Ответ 24

На мой взгляд, лучший способ - использовать функцию 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/

Ответ 25

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

 $.each([ 52, 97 ], function( index, value ) {
      alert( index + ": " + value );
 });

Ответ 26

Это не на 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
    }

Ответ 27

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

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

Ответ 28

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

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

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

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

Ответ 29

var x = [4, 5, 6];
for (i = 0, j = x[i]; i < x.length; j = x[++i]) {
    console.log(i,j);
}

Много чище...

Ответ 30

Уверен, что он неэффективен и многие его презирают, но он один из ближайших к упомянутому:

var myStringArray = ["Hello","World"];
myStringArray.forEach(function(f){
    // Do something
})