Вопрос: Цикл через массив в JavaScript


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

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

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


2372


источник


Ответы:


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

var myStringArray = ["Hello","World"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
    alert(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) {
  alert(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...
    alert("prop: " + prop + " value: " + obj[prop])
  }
}

В приведенном выше примере hasOwnPropertyметод позволяет вам перечислять только собственные свойства , вот и все, только свойства, которые физически имеет объект, не унаследованные свойства.

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


3016



Да, но только если ваша реализация включает for... ofфункция, введенная в ECMAScript 2015 (релиз «Гармония»).

Он работает следующим образом:

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

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

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

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


832



Вы можете использовать map, который представляет собой метод функционального программирования, который также доступен на других языках, таких как: питон а также 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,


388



In JavaScript it's not advisable to loop through an Array with a for-in loop, but it's better using a for loop such as:

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

It's optimized as well ("caching" the array length). If you'd like to learn more, read my post on the subject.


101



for (var s of myStringArray) {

(Directly answering your question: now you can!)

Most other answers are right, but they do not mention (as of this writing) that ECMA Script  6  2015 is bringing a new mechanism for doing iteration, the for..of loop.

This new syntax is the most elegant way to iterate an array in javascript (as long you don't need the iteration index), but it is not yet widely supported by the browsers.

It currently works with Firefox 13+, Chrome 37+ and it does not natively work with other browsers (see browser compatibility below). Luckily we have JS compilers (such as Babel) that allow us to use next-generation features today.

It also works on Node (I tested it on version 0.12.0).

Iterating an array

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

Iterating an array of objects

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

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

Iterating a generator:

(example extracted from 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;
  }
}

Compatibility table: http://kangax.github.io/es5-compat-table/es6/#For..of loops

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

}


90



Opera, Safari, Firefox and Chrome now all share a set of enhanced Array methods for optimizing many common loops.

You may not need all of them, but they can be very useful, or would be if every browser supported them.

Mozilla Labs published the algorithms they and WebKit both use, so that you can add them yourself.

filter returns an array of items that satisfy some condition or test.

every returns true if every array member passes the test.

some returns true if any pass the test.

forEach runs a function on each array member and doesn't return anything.

map is like forEach, but it returns an array of the results of the operation for each element.

These methods all take a function for their first argument and have an optional second argument, which is an object whose scope you want to impose on the array members as they loop through the function.

Ignore it until you need it.

indexOf and lastIndexOf find the appropriate position of the first or last element that matches its argument exactly.

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

81



Use the while loop...

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

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

And for the reverse order, an even more efficient loop

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

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

Or the classical for loop

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

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

Reference: http://www.sitepoint.com/google-closure-how-not-to-write-javascript/


62



Intro

Since my time in college, I've programmed in Java, JavaScript, Pascal, ABAP, PHP, Progress 4GL, C/C++ and possibly a few other languages I can't think of right now.

While they all have their own linguistic idiosyncrasies, each of these languages share many of the same basic concepts. Such concepts include procedures / functions, IF-statements, FOR-loops, and WHILE-loops.


A traditional for-loop

A traditional for loop has three components:

  1. The initialization: executed before the look block is executed the first time
  2. The condition: checks a condition every time before the loop block is executed, and quits the loop if false
  3. The afterthought: performed every time after the loop block is executed

These three components are separated from each other by a ; symbol. Content for each of these three components is optional, which means that the following is the most minimal for loop possible:

for (;;) {
    // Do stuff
}

Of course, you will need to include an if(condition === true) { break; } or an if(condition === true) { return; } somewhere inside that for-loop to get it to stop running.

Usually, though, the initialization is used to declare an index, the condition is used to compare that index with a minimum or maximum value, and the afterthought is used to increment the index:

for (var i = 0, length = 10; i < length; i++) {
    console.log(i);
}

Using a traditional for loop to loop through an array

The traditional way to loop through an array, is this:

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

Or, if you prefer to loop backwards, you do this:

for (var i = myArray.length - 1; i > -1; i--) {
    console.log(myArray[i]);
}

There are, however, many variations possible, like for example this one:

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

... or this one ...

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

... or this one:

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

Whichever works best is largely a matter of both personal taste and the specific use case you're implementing.

Note that each of these variations is supported by all browsers, including very very old ones!


A while loop

One alternative to a for loop is a while loop. To loop through an array, you could do this:

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

Like traditional for loops, while loops are supported by even the oldest of browsers.

Also, note that every while loop can be rewritten as a for loop. For example, the while loop hereabove behaves the exact same way as this for-loop:

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

For...in and for...of

In JavaScript, you can also do this:

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

This should be used with care, however, as it doesn't behave the same as a traditional for loop in all cases, and there are potential side-effects that need to be considered. See Why is using "for...in" with array iteration a bad idea? for more details.

As an alternative to for...in, there's now also for for...of. The following example shows the difference between a for...of loop and a for...in loop:

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
}

Additionally, you need to consider that no version of Internet Explorer supports for...of (Edge 12+ does) and that for...in requires at least Internet Explorer 10.


Array.prototype.forEach()

An alternative to for-loops is Array.prototype.forEach(), which uses the following syntax:

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

Array.prototype.forEach() is supported by all modern browsers, as well as Internet Explorer 9 and later.


Libraries

Finally, many utility libraries also have their own foreach variation. AFAIK, the three most popular ones are these:

jQuery.each(), in jQuery:

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

_.each(), in Underscore.js:

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

_.forEach(), in Lodash.js:

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

47