arrays перебор - Цикл через массив в JavaScript




массива массивы (25)

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

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

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


Answers

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

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должно быть использован.


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

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

Или классический 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/


Да, но только если ваша реализация включает функцию ..., введенную в 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 совместим с предыдущей версией спецификации ECMAScript (которая исключает, например, версии Internet Explorer до 9), вы можете использовать метод forEach вместо цикла. В этом случае вы передаете функцию, которая будет вызываться для каждого элемента массива:

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

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

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

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

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


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

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

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

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

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

некоторые возвращают 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;
})();

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


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

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

Результаты :

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


На мой взгляд, лучший способ - использовать функцию Array.forEach. Если вы не можете использовать это, я бы предложил получить полиполк из MDN, чтобы сделать i доступным, это, безусловно, самый безопасный способ перебора массива в 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;
});

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

использование обычного стиля 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/


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

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

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

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

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

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.
}

Или если вы действительно хотите получить идентификатор и действительно классический цикл:

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 .


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

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


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

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

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

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

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


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


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


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

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


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

Например:

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

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

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>

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

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

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

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

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

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


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

или лучше и чище использовать во время цикла:

var myStringArray = ["item1","item2"],i = myStringArray.length;
while(i--) {
   // do something with fruits[i]
}

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

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

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

var arr = [1, 2, 3, 4, 5];

Это решения:

1) для цикла

Для цикла - это общий способ циклирования массивов в JavaScript, но не считается самым быстрым решением для больших массивов:

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

2) Пока цикл

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

let i=0;

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

3) Делайте, пока
делаете, делая то же самое, что и с некоторыми различиями синтаксиса, как показано ниже:

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.

Подробнее >> here :


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

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

var someArray = ["some", "example", "array"];

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

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

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

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

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

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

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

for (String item : someArray) {
}

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


для (var s myStringArray) {

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

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

}


Принимая во внимание ES6, я хотел бы добавить свою собственную ложку сахара и предложить еще один подход к переходу на свойства объекта.

Поскольку простой JS-объект не является iterable только из коробки, мы не можем использовать for..ofцикл для итерации по его контенту. Но никто не может остановить нас, чтобы сделать его итерабельным .

Давайте будем иметь bookобъект.

let book = {
  title: "Amazing book",
  author: "Me",
  pages: 3
}

book[Symbol.iterator] = function(){

  let properties = Object.keys(this); // returns an array with property names
  let counter = 0;
  let isDone = false;

  let next = () => {
    if(counter >= properties.length){
      isDone = true;
    }
    return { done: isDone, value: this[properties[counter++]] }
  }

  return { next };
}

Поскольку мы сделали это, мы можем использовать его так:

for(let pValue of book){
  console.log(pValue);
}
------------------------
Amazing book
Me
3

Или, если вы знаете мощность generators ES6 , вы наверняка можете сделать код намного короче.

book[Symbol.iterator] = function *(){

  let properties = Object.keys(this);
  for (let p of properties){
    yield this[p];
  }

}

Конечно, вы можете применить такое поведение для всех объектов, сделав их Objectитерабельными на prototypeуровне.

Object.prototype[Symbol.iterator] = function() {...}

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

let pValues = [...book];
console.log(pValues);
-------------------------
["Amazing book", "Me", 3]

Или вы можете использовать назначение destructuring :

let [title, , pages] = book; // notice that we can just skip unnecessary values
console.log(title);
console.log(pages);
------------------
Amazing book
3

Вы можете проверить JSFiddle со всем приведенным выше кодом.





javascript arrays loops for-loop