it-swarm.com.ru

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

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

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

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

2640
Mark Szymanski

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

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

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

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

3268
CMS

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

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

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

Но если даже это слишком много, чтобы предполагать, и вы хотите что-то, что работает в all версиях JavaScript, тогда вы должны использовать явный цикл подсчета. Самая безопасная версия, которая правильно обрабатывает разреженные массивы, выглядит примерно так:

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

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

998
Mark Reed

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

415
hasen

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

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

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

107
sebarmeli

for (var of of myStringArray) {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

}

101
Marlon Bernardes

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

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

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

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

every возвращает 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;
})();
84
kennebec

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

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

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

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

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

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

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

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

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

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

62
Timo Huovinen

Вступление

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

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


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

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

  1. Инициализация: выполняется перед первым выполнением блока просмотра
  2. Условие: проверяет условие каждый раз перед выполнением блока цикла и выходит из цикла, если false
  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);
}

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

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


while цикл

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

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

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

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

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

For...in и for...of

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

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

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

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

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

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

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

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


Array.prototype.forEach()

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

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

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


Библиотеки

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

jQuery.each() , в jQuery :

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

_.each() , in Underscore.js :

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

_.forEach() , в Lodash.js :

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

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

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

36
Phrogz

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

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

28
Yuci

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

26
RizN81

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

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

26
Gabriel

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

Например:

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

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

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

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

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

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

22
Alireza

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

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

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

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

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

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

19
justingordon

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

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

 Performamce results

Результаты :

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

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

18
colxi

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

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

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/

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

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

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

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

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

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

for (String item : someArray) {
}

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

16
Stijn de Witt

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

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>
14
molokoloco

Есть несколько способов сделать это в 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>

14
Shubham Khatri

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

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.

14
kirilloid

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

10
Alongkorn Chetasumon

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

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

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

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

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

9
Juanjo Salvador

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

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

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

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

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

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

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

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/

9
Espen

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

[].forEach.call(document.getElementsByTagName('pre'), function(e){ 
   console.log(e);
})
8
victorq10
var x = [4, 5, 6];
for (i = 0, j = x[i]; i < x.length; j = x[++i]) {
    console.log(i,j);
}

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

8
staticd

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

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

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

7
Muhammad Alvin

Простое решение в одну строку

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

// solution
arr.map((e) => {
  console.log(e);
  return e;
});

7
BILAL AHMAD

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

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

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

_.forEach([1, 2], (value) => {
  console.log(value);
});
5
Andrew

Ну как на счет этого:

for (var key in myStringArray) {
    console.log(myStringArray[key]);
}
5
Sambhav Sharma
var myStringArray = ["hello", "World"];
myStringArray.forEach(function(val, index){
   console.log(val, index);
})
5
Amit Jamwal

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

for (var i = 0; i < myStringArray.length; i++) {
    // Do something
}
4
user6139250

Резюме:

При переборе массива мы часто хотим достичь одной из следующих целей:

  1. Создайте новый массив, оставьте исходный без изменений: используйте map()
  2. Выполните действие с/над каждым элементом массива и, возможно, измените массив: используйте for..of, forEach() или обычный цикл for

Примеры:

const arr1 = [1, 2, 3];

const arr2 = arr1.map(el => el * 2);

// with map we create a new arr2, arr1 is left untouched
console.log(arr2, arr1);


// regular for loop
for (let i = 0; i < arr1.length; i++) {
  console.log(arr1[i]);
}

console.log('\n');

// for of loop
for (let el of arr1) {
  console.log(el);

}

console.log('\n');


// forEach()
arr1.forEach(el => {
  console.log(el)
})

Какой использовать?

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

  1. Если вы хотите манипулировать массивом, но оставить старый массив нетронутым (например, функциональное программирование), вы можете лучше всего использовать map() для итерации. Если вам не нужно возвращать новый массив, не используйте map(). map() имеет самую низкую производительность среди всех циклических методов.
  2. Когда производительность играет роль, когда вам нужно перебрать очень много, обычный цикл for:

for(let i=0; i < arr.length; i++) {}

часто (может отличаться из-за различий в движке JS) лучшая производительность, потому что это самая итеративная форма итерации. 

4
Willem van der Veen
var obj = ["one","two","three"];

for(x in obj){
    console.log(obj[x]);
}
3
Dan Chill

Зацикливание массива рекурсивно 

const data = ['one', 'two', 'three']

const loop = (items, index=0) => {
  if (items.length === index) {
    return;
  }
  console.log(items[index], index)
  loop(items, index+=1)
}

loop(data)
2
John Ottenlips

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>

0
Shijo Rs