Проведіть масив через JavaScript


3144

У Java ви можете використовувати forцикл для переміщення об'єктів у масиві таким чином:

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

Чи можете ви зробити те ж саме в JavaScript?


5
Гаразд, тому я трохи заплутався, нормально використовувати розширений цикл, коли ви отримуєте доступ до об'єктів? А використовувати для заповнення послідовний? Це правильно?
Марк Шиманський

45
ні, це дійсно просто, об'єкти масиву мають числові індекси, тому потрібно повторити ці індекси в числовому порядку, послідовний цикл гарантує, що розширений for-in цикл перераховує властивості об'єкта без конкретного порядку, а також перераховує успадковані властивості. .. для ітерації над масивами завжди рекомендуються послідовні петлі ...
CMS


6
jsben.ch/#/Q9oD5 <= Тут орієнтир групи рішень для циклічного перегляду масивів
EscapeNetscape

3
@CMS Ні, це не дуже просто. На всіх інших мовах це дуже просто. Це смішно складно в JS, де ти маєш inі ofщо можна і використовувати, і робити різні речі. Тоді у вас є forEachі негарна, і дратівлива петля, заснована на індексах. Кожна інша сучасна мова робить циклічне перетворення колекції легким та простим, без сюрпризів чи плутанини. JS теж міг, але це не так.
jpmc26

Відповіді:


3957

У вас є кілька варіантів:

1. Послідовна forпетля:

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

Плюси

  • Працює в кожному середовищі
  • Ви можете використовувати breakта continueперевіряти оператори управління потоком

Мінуси

  • Занадто багатослівний
  • Імператив
  • Легко мати помилки один за одним (іноді їх також називають помилкою помилки )

2. Array.prototype.forEach

Специфікація ES5 представила безліч корисних методів масиву, один з них, Array.prototype.forEachі це дає нам стислий спосіб переглядати масив:

const array = ["one", "two", "three"]
array.forEach(function (item, index) {
  console.log(item, index);
});

Будучи майже десять років з моменту написання, що специфікація ES5 була випущена (грудень 2009 р.), Вона була реалізована майже всіма сучасними двигунами в настільному, серверному та мобільному середовищі, тому їх безпечно використовувати.

А з синтаксисом функції стрілки ES6 це ще більш лаконічно:

array.forEach(item => console.log(item));

Функції стрілок також широко застосовуються, якщо ви не плануєте підтримувати старовинні платформи (наприклад, IE11); Ви також можете безпечно їхати.

Плюси

  • Дуже короткий і лаконічний.
  • Декларативний

Мінуси

  • Неможливо використовувати break/continue

Зазвичай ви можете замінити необхідність breakвиходу з імперативних циклів, фільтруючи елементи масиву перед ітерацією, наприклад:

array.filter(item => item.condition < 10)
     .forEach(item => console.log(item))

Майте на увазі, якщо ви ітератуєте масив для створення іншого масиву з нього , вам слід скористатися map, я багато разів бачив цей антидіапазон.

Антидіаграма:

const numbers = [1,2,3,4,5], doubled = [];

numbers.forEach((n, i) => { doubled[i] = n * 2 });

Правильний варіант використання карти :

const numbers = [1,2,3,4,5];
const doubled = numbers.map(n => n * 2);

console.log(doubled);

Крім того, якщо ви намагаєтеся зменшити масив до значення, наприклад, ви хочете підсумувати масив чисел, слід скористатися методом зменшення .

Антидіаграма:

const numbers = [1,2,3,4,5];
const sum = 0;
numbers.forEach(num => { sum += num });

Правильне використання редуктора :

const numbers = [1,2,3,4,5];
const sum = numbers.reduce((total, n) => total + n, 0);

console.log(sum);

3. for-ofЗаява ES6

Стандарт ES6 вводить поняття ітерабельних об'єктів і визначає нову конструкцію для переміщення даних, for...ofзаяву.

Це твердження працює для будь-якого об’єкта, який можна перетворити, а також для генераторів (будь-якого об'єкта, який має [Symbol.iterator]властивість).

Об'єкти масиву за визначенням є вбудованими ітерабелями в ES6, тому ви можете використовувати цей оператор на них:

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

Плюси

  • Він може перебирати велику кількість об'єктів.
  • Може використовувати звичайні оператори управління потоком ( break/ continue).
  • Корисно для ітерації послідовно асинхронних значень.

Мінуси

  • Якщо ви орієнтуєтесь на більш старі веб-переглядачі, транспільований вихід може вас здивувати .

Не використовувати for...in

@zipcodeman пропонує використовувати for...inоператор, але для ітераційних масивів for-inслід уникати цього твердження, щоб перерахувати властивості об'єкта.

Його не слід використовувати для об’єктів, подібних до масиву, оскільки:

  • Порядок ітерації не гарантується; індекси масиву можуть не відвідуватися в числовому порядку.
  • Спадкові властивості також перераховуються.

Другий момент полягає в тому, що він може доставити вам багато проблем, наприклад, якщо ви поширите Array.prototypeоб’єкт, щоб він включив туди метод, це властивість також буде перераховано.

Наприклад:

Array.prototype.foo = "foo!";
var array = ['a', 'b', 'c'];

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

Вищевказаний код консолірує журнали "a", "b", "c" та "foo!".

Це буде особливо проблемою, якщо ви використовуєте деяку бібліотеку, яка в значній мірі покладається на розширення нативних прототипів (наприклад, MooTools).

Як for-inя вже говорив, висловлювання для перерахування властивостей об'єкта, наприклад:

var obj = {
    "a": 1,
    "b": 2,
    "c": 3
};

for (var prop in obj) {
    if (obj.hasOwnProperty(prop)) { 
        // or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
        console.log("prop: " + prop + " value: " + obj[prop])
    }
}

У наведеному вище прикладі hasOwnPropertyметод дозволяє перераховувати лише власні властивості , ось це, лише ті властивості, якими об'єкт фізично має, ніяких успадкованих властивостей.

Я рекомендую вам прочитати наступну статтю:


21
Саме по цій причині (по CMS ним сам) stackoverflow.com/questions/1885317 / ...
OscarRyz

15
@DoubleGras, я думаю, що це думка, яку поділяють не всі. Дивіться: stackoverflow.com/questions/5752906/… або groups.google.com/forum/?fromgroups#!topic/jsmentors/…
Matthijs Wessels

3
Усі, хто думає, що вам потрібно кешувати довжину ... Будь ласка, подивіться мою відповідь, вам навіть не потрібно одноразово отримувати доступ до неї, не кажучи вже про кешування: for (var i = 0, item; item = myStringArray [i]; i ++) {/ * використовуйте предмет тут * /}
Stijn de Witt

15
@StijndeWitt Ні, тому що перерви , якщо у вас є якесь - або «falsey» значення в масиві: false, undefined, 0, "", NaN.
Фрогз

6
jsperf.com/caching-array-length/4 Ось тест на предмет того, чи варто кешувати довжину масиву в циклі Javascript
Енріко

1114

Так, якщо припустити, що ваша реалізація включає в себе функцію for...,of запроваджену в ECMAScript 2015 (випуск "Гармонія") ... що ці дні є досить безпечним.

Це працює так:

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

Або ще краще, оскільки ECMAScript 2015 також надає блок-області змінних:

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

(Змінна sє різною для кожної ітерації, але все ще може бути оголошена constвсередині корпусу циклу, доки вона не буде змінена там.)

Примітка про розріджені масиви: масив у JavaScript може насправді не зберігати стільки елементів, скільки повідомляється в ньому length; це повідомлене число просто на один більший за найвищий індекс, у якому зберігається значення. Якщо масив містить менше елементів, ніж зазначено його довжиною, його вважають рідким . Наприклад, абсолютно законно мати масив з елементами лише в індексах 3, 12 і 247; lengthтакого масиву повідомляється як 248, хоча на самому ділі тільки зберігати 3 значення. Якщо ви спробуєте отримати доступ до елемента в будь-якому іншому індексі, з'явиться масив, який має undefinedтам значення. Тож, коли ви хочете "провести цикл" масиву, у вас є питання, на яке потрібно відповісти: чи хочете ви перевести цикл на весь діапазон, вказаний його довжиною та процесомundefineds для відсутніх елементів, або ви хочете лише обробити фактично наявні елементи? Для обох підходів є безліч застосувань; це просто залежить від того, для чого ви використовуєте масив.

Якщо ви повторюєте масив з for.. of, тіло циклу виконується lengthразів, і змінна керування циклом встановлюється undefinedдля будь-яких елементів, які насправді відсутні в масиві. Залежно від деталей вашого коду "зроби щось з", така поведінка може бути тим, що ти хочеш, але якщо ні, ти повинен використовувати інший підхід.

Звичайно, деякі розробники не мають іншого вибору , крім як використовувати інший підхід в будь-якому випадку, тому що з якоїсь - то причини вони орієнтації версію JavaScript , який ще не підтримується for... of.

Поки ваша реалізація JavaScript відповідає попередній редакції специфікації ECMAScript (яка виключає, наприклад, версії Internet Explorer до 9), ви можете використовувати Array#forEachметод ітератора замість циклу. У цьому випадку ви передаєте функцію, яку потрібно викликати для кожного елемента масиву:

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

На відміну від for... of, .forEachфункція викликає лише ті елементи, які фактично є в масиві. Якщо ми передамо наш гіпотетичний масив з трьома елементами і довжиною 248, він викличе функцію лише три рази, а не 248 разів. Він також розрізняє відсутні елементи та елементи, які фактично встановлені undefined; для останнього він все одно буде викликати функцію, передаючи undefinedв якості аргументу. Якщо це, як ви хочете обробляти розріджені масиви, .forEachможе бути шлях , навіть якщо інтерпретатор підтримує for... of.

Остаточний варіант, який працює у всіх версіях JavaScript, - це явний цикл підрахунку . Ви просто рахуєте від 0 до одного менше довжини і використовуєте лічильник як індекс. Основний цикл виглядає так:

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  s = myStringArray[i];
  // ... do something with s ...
}

Однією з переваг такого підходу є те, що ви можете вибрати, як обробляти рідкісні масиви; Наведений вище код буде працювати тіло циклу повні lengthраз, з sнабором для undefinedбудь-яких елементів, яких бракує, так само як for.. of. Якщо ви хочете обробити лише фактично наявні елементи розрідженого масиву, наприклад .forEach, ви можете додати простий inтест на індекс:

var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
  if (i in myStringArray) {
    s = myStringArray[i];
    // ... do something with s ...
  }
}

Присвоєння значення довжини локальній змінній (на відміну від включення повного myStringArray.lengthвираження в стан циклу) може суттєво змінити продуктивність, оскільки вона щоразу пропускає пошук властивості; використовуючи Rhino на моїй машині, швидкість становить 43%.

Ви можете побачити кешування довжини, виконане в пункті ініціалізації циклу, як це:

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

Явний цикл підрахунку також означає, що ви маєте доступ до індексу кожного значення, якщо ви цього хочете. Індекс також передається як додатковий параметр функції, до якої ви передаєте forEach, тож ви також можете отримати доступ до нього таким чином:

myStringArray.forEach( function(s, i) {
   // ... do something with s and i ...
});

for... ofне дає вам індексу, пов’язаного з кожним об'єктом, але поки об'єкт, над яким ви повторюєтесь, насправді є Array( for.. ofпрацює для інших ітерабельних типів, які можуть не мати цього методу), ви можете використовувати масив метод #entries, щоб змінити його в масив [індекс, елемент] пар, а потім повторити це:

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

for... inсинтаксис вже зазначалося іншими для циклу за властивостями об'єкта; оскільки масив у JavaScript - це лише об'єкт із числовими іменами властивостей (та властивість, що автоматично оновлюється length), ви можете теоретично перебирати на нього масив. Але проблема полягає в тому, що він не обмежує себе числовими значеннями властивостей (пам’ятайте, що навіть методи насправді є лише властивостями, значенням яких є закриття), а також не гарантується повторення даних у числовому порядку. Тому for...in синтаксис не повинен використовуватися для циклічного перегляду через масиви.


21
Зауважте, що деякі інтерпретатори (наприклад, V8) автоматично кешують довжину масиву, якщо код буде викликаний достатньо разів, і він виявить, що довжина не змінюється циклом. Хоча кешування довжини все ще приємно, воно може не забезпечити збільшення швидкості, коли ваш код викликається достатньо разів, щоб фактично змінити значення.
Фрогз

2
@ mark-reed. Чи можете ви поясніть, чому ви використовували i in myStringArrayу своєму прикладі? Як це може бути помилковим?
Денис V

2
@DenisV: false. a=[1,2,3,4]; delete a[2]; for (j in a) { console.log(j); } Виходи 0, 1, 3 і 4. a.lengthвсе ще 5.
Марк Рід

1
Я не пропоную for j in a. Я демонструю, що inперевірка не є надмірною, як ви заявляли, як показав усі індекси та показав, що є один між 0, а length-1його немає. Я також міг щойно надрукувати 2 in a, що справді false, незважаючи на те, що ви сказали, що це неможливо.
Марк Рід

2
@GrijeshChauhan - правильно. Наприклад, IE через версію 8 не підтримує його. Дивіться це питання .
Марк Рід

442

Ви можете використовувати 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;});

А тепер х є [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.


7
Ні, але це може бути потужнішим. перевірте це: joelonsoftware.com/items/2006/08/01.html
травня

97
Цей конкретний приклад, мабуть, краще реалізувати за допомогою Array.forEach. mapпризначений для створення нового масиву.
харто

21
@hasen, Array.prototype.mapметод є частиною стандарту ECMAScript 5-го видання, ще не доступний у всіх реалізаціях (наприклад, у IE його відсутні), також для ітерації над масивом, я думаю, що Array.prototype.forEachметод є більш семантично правильним ... також, будь ласка, не ' t пропоную заяву про подачу, детальну інформацію див. у моїй відповіді :)
CMS

3
Різниця між forEachі в mapтому, що перший не повертає результатів ітерації. map(іноді ака collect, але сильно відрізняється від apply) - це явне перетворення кожного елемента масиву у відповідний результат; це зіставлення 1 на 1 , звідси і назва. Це частина цілого сімейства операцій, які включають reduce(які виробляють єдиний результат з усього масиву) і filter(які виробляють підмножину вихідного масиву) тощо. В той час, як forEachпросто робиться щось із кожним елементом, семантика не визначена.
Марк Рід

4
Downvote тому, що якщо ви насправді щось не картографуєте, то використання [] .map вводить в оману. [] .forEach має смисловий сенс, а також передає ті самі три аргументи функції.
gengkev

120

У JavaScript не рекомендується проводити цикл через масив із циклом for-in, але краще використовувати forцикл, наприклад:

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

Це також оптимізовано ("кешування" довжини масиву). Якщо ви хочете дізнатися більше, прочитайте мій пост на цю тему .


2
myArray.forEach (функція (obj) {}); все ще найкращий
Ян Сверре

крихітне покращення: ++iзамість цього можна скористатисяi++
roberkules

14
++iстара оптимізація школи , що сучасні компілятори для вас в циклі , так як давно :) stackoverflow.com/a/1547433/1033348
ngryman

6
Ви повинні бути обережними, використовуючи цю петлю. Я почав його використовувати і мені важко було відслідковувати помилку через одну помилку, яку я зробив. Якщо ви вкладете дві петлі так: jsfiddle.net/KQwmL/1 . Ви повинні бути обережними, щоб назвати var len по-різному в двох петлях, інакше друга петля замінить першу.
Руй Маркес

1
Rui Marques - ви можете назвати свою змінну i_stopабо i_endзамість неї len. Це так само читабельно (якщо не більше!), І ви, природно, уникнете подібних проблем (оскільки отримаєте інший цикл, наприклад, j_stop).
Чіп Хогг

118

для (нехай з 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/#For..of циклів

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

}


Якщо ви використовуєте ES6, я б запропонував const sзамістьvar s
joeytwiddle

У моїх тестах на великих масивах, використовуючи var s of arrмайже подвійний (1.9x) час виконання порівняно з використанням простого лічильника для циклу та отримання елементів за індексом у nodejs
theferrit32

Чому такі дивні речі в першому та останньому рядку?
Пітер Мортенсен

91

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

Можливо, вони вам не знадобляться, але вони можуть бути дуже корисними або, якби кожен браузер їх підтримував.

Mozilla Labs опублікував алгоритми, якими вони користуються і WebKit , так що ви можете їх додати самостійно.

filter повертає масив елементів, які відповідають певній умові або тесту.

кожен повертає істину, якщо кожен член масиву проходить тест.

деякі повертають істину, якщо якісь проходять тест.

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

1
Доповнення: IE підтримує forEach з версії 9, дивіться дляEach Method MSDN
rwitzel

75

Вступ

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

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


Традиційний- forпетля

Традиційний forцикл має три компоненти:

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

Ці три компоненти відокремлені один від одного ;символом. Вміст для кожного з цих трьох компонентів є необов’язковим, а це означає, що наступним є мінімально forможливий цикл:

for (;;) {
    // Do stuff
}

Звичайно, вам потрібно буде включити if(condition === true) { break; } або if(condition === true) { return; }десь усередині цього for-пучка, щоб змусити його перестати працювати.

Однак зазвичай ініціалізація використовується для оголошення індексу, умова використовується для порівняння цього індексу з мінімальним або максимальним значенням, а наступна думка використовується для збільшення індексу:

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

Використання традиційного forциклу для циклічного перегляду масиву

Традиційний спосіб провести цикл через масив:

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

Або, якщо ви віддаєте перевагу циклу назад, зробіть це:

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

Однак можливе багато варіантів, як, наприклад, цей:

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

... або цей ...

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

... або цей:

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

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

Зауважте, що кожен із цих варіантів підтримується всіма браузерами, включаючи дуже старі!


whileцикл

Однією з альтернатив forциклу є whileпетля. Щоб провести цикл через масив, ви можете зробити це:

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

Як і традиційні forпетлі, 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...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 та новіших версій.


Бібліотеки

Нарешті, у багатьох бібліотек утиліт також є своя 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);
});

68

Використовуйте цикл 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/


21
Перший приклад синтаксису "while" не працюватиме, якщо будь-який з елементів масиву є хибним.
Кріс Купер

2
... і цей цикл у той час, як еквівалентний: for (var i = 0, item; item = items [i]; i ++), що забирає необхідність заздалегідь оголошувати змінні індексу та елемента ...
Stijn de Witt


39

Якщо потрібно короткий спосіб написати швидкий цикл, і ви можете повторити його в зворотному порядку:

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 під час ітерації.


16
Для людей, які не розуміють настільки геніального: вираз i-- спочатку оцінюється і дозволяє циклу продовжуватись, коли він не є фальшивим ... Потім лічильник зменшується. Як тільки я стає нульовим, він вирветься з циклу, оскільки в Javascript - нульове значення.
Штійн де Вітт

5
фальшивий? Ви маєте на увазі фальси. Давайте всі дотримуватись належної термінології, щоб уникнути плутанини;)
danwellman

4
Я бачив, як термін "фальшивка" використовується людьми, яких я вважаю гуру. Якщо для них це досить добре, для мене це досить добре. Також розчарований, коли мій коментар, який є насправді онтопічним, і додає пояснення / розуміння, отримує 0 оновлень, але коментар про те, що нітрохи на термін у моєму коментарі отримує 4. А ну просто питання пріоритетів.
Штійн де Вітт

"Вилучення довжини"? Довжина зберігається як ціле число в масиві, вона не вимірюється кожен раз, коли ви отримуєте доступ до неї. Тут немає користі в копіюванні значення довжини в іншу змінну.
Різне

1
@Mouscellaneous У наші дні, звичайно, немає; за минулі роки ітерація масивів JavaScript кешування довжини на стороні JavaScript (замість того, щоб поширюватись на всю реалізацію) була явним посиленням перф (при мікрооптимізації). Наприклад, for (var i=0,len=array.length;i<len;++i)була звичайна, розумна петля для написання.
Фрогз

36

Деякі використовують випадки циклічного перегляду масиву функціональним способом програмування в 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);

введіть тут опис зображення

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

введіть тут опис зображення

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

Список літератури


30

Існує спосіб зробити це там, де у вас в циклі дуже мало неявної області дії та усунути зайві змінні.

var i = 0,
     item;

// note this is weak to sparse arrays or falsey values
for ( ; item = myStringArray[i++] ; ){ 
    item; // This is the string at the index.
}

Або якщо ви дійсно хочете отримати ідентифікатор і мати дійсно класичний forцикл:

var i = 0,
    len = myStringArray.length; // cache the length

for ( ; i < len ; i++ ){
    myStringArray[i]; // Don't use this if you plan on changing the length of the array
}

Сучасні браузери всіх методи підтримки ітераторів forEach, map, reduce, filterа також безліч інших методів на масив прототипі .


3
Зауважте, що деякі інтерпретатори (наприклад, V8) автоматично кешують довжину масиву, якщо код буде викликаний достатньо разів, і він виявить, що довжина не змінюється циклом.
Фрогз

Дякую за інформацію @Phrogz Це правда, що VM може зробити багато оптимізацій, але оскільки у старих браузерів цього немає, все-таки найкраща практика оптимізувати його, оскільки це так дешево.
Габріель

1
@Gabriel: Чому? Наведіть приклади реального світу, які показують, що не кешування довжини насправді вузьким місцем продуктивності. Я слідую за тим, щоб "передчасна оптимізація - корінь всього зла". Я виправлю цю петлю, яка насправді створює проблему, коли я зіткнусь із нею ...
Stijn de Witt

1
@StijndeWitt imo - це лише стилістичне питання. Чесно кажучи, я більше не використовую циклів, а для того, щоб робити ці речі, такі як _.each, _.map тощо тощо. Коли я писав подібні цикли, я кешував довжину насамперед, щоб усі мої змінні оголошення знаходилися в одному місці, у верхній частині моєї функції. Дотримуючись моїх порад з цього приводу не впливає на будь-яке застосування в реальному світі. Передчасна оптимізація - це дуже погано, але якщо оптимізація трапляється в результаті стилістичних рішень, я не думаю, що це насправді має значення.
Габріель

1
@Gabriel Я вважаю, що JavaScript вже підтримує функцію карти на масивах, не потрібно вводити для цього додаткову лібу.
Ноз

28

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


27

Я настійно рекомендую використовувати бібліотеку underscore.js . Він надає вам різні функції, які ви можете використовувати для ітерації масивів / колекцій.

Наприклад:

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

7
Для нових відкривачів цього питання я хотів би лише зазначити Ло-Деш , духовного спадкоємця підкреслення, який багато в чому покращує його.
Марк Рід

3
Навіщо використовувати, underscoreякщо до методу ECMA-262 був доданий forEachметр. Нативний код завжди кращий.
Walter Chapilliquen - wZVanG

27

Цикл масиву:

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

27

Так , ви можете зробити те ж саме в 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) Поки петля

Певний час цикл вважається найшвидшим способом проходження циклу через довгі масиви, але він зазвичай менш використовується в коді JavaScript:

let i=0;

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

3) Робіть, поки
A do whileробить те саме, що і whileз деякою різницею синтаксису, як нижче:

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

Це основні способи робити петлі JavaScript, але є ще кілька способів зробити це.

Також ми використовуємо for inцикл для перегляду об'єктів у JavaScript.

Також зверніть увагу на map(), filter(), reduce()функцій і т.д. на масив в JavaScript. Вони можуть робити речі набагато швидше та краще, ніж використання whileта for.

Це хороша стаття, якщо ви хочете дізнатися більше про асинхронні функції над масивами в JavaScript.

В даний час функціональне програмування зробило неабиякий сплеск у світі розвитку. І не дарма: функціональні методи можуть допомогти вам написати більш декларативний код, який легше зрозуміти на перший погляд, рефактор та тест.

Одним з наріжних каменів функціонального програмування є його спеціальне використання списків та операцій зі списком. І ці речі є саме такими, якими вони звучать: масиви речей та речі, які ви їм робите. Але функціональне мислення сприймає їх дещо інакше, ніж ви могли очікувати.

Ця стаття детально ознайомиться з тим, як мені подобається називати операції зі списком "великої трійки": карта, фільтр та зменшення. Обгортання головою навколо цих трьох функцій є важливим кроком до можливості писати чистий функціональний код і відкриває двері для надзвичайно потужних прийомів функціонального та реактивного програмування.

Це також означає, що вам більше не доведеться писати цикл знову.

Детальніше >> тут :


Чи дійсно є різниця в продуктивності перед циклом for і час, коли повторюється масив? У мене було враження, що відмінності були в першу чергу синтаксичними
she

24

Якщо когось цікавить ефективність роботи декількох механізмів для ітерацій масиву, я підготував такі тести 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()є найповільнішими наближеннями, ймовірно, як наслідок накладного виклику функції .


краще використовувати i = i +1замістьi++
DarckBlezzer

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

@PowerStat Ви можете надати посилання або посилання на це? Я ніколи про це не чула, звучить цікаво ...
colxi

1
@colxi Для таких цікавих речей слід прочитати хардкор C ++ з Herb Sutter та Scott Meyers. Річ ++ i vs i ++ - це з книги: Винятковий C ++: 47 Інженерні головоломки, проблеми програмування та рішення - Я те, що ви також можете знайти його на gotw.ca, але це може бути доведено для кожної мови програмування.
PowerStat

21

Якщо ви використовуєте бібліотеку 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парне, навіть якщо воно є простим значенням рядка чи числа.) Метод повертає свій перший аргумент - об'єкт, який був ітератором.


9
jQuery для всього?
Виняток

6
Погоджено з винятком. Не варто недооцінювати вплив зайвих залежностей. Я б радив проти цього, за винятком коду, який так чи інакше використовує jQuery.
Штійн де Віт

2
Оновлення: У ці дні ви можете використовувати Array.forEach, щоб отримати майже однаковий ефект із нативними масивами.
Штійн де Вітт

20

Я ще не бачив цієї варіації, яка мені особисто подобається найкраще:

Дано масив:

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 .. довжина-1, вам потрібна конструкція for (var i = 0; i <someArray.length; ++ i), але все ще потрібна ifвнутрішня петля перевірити, чи фактично визначений елемент у поточному індексі.

Також, як згадує CMS у коментарі нижче, ви можете використовувати це лише для масивів, які не містять жодного фальшивого значення. Масив рядків із прикладу працює, але якщо у вас порожні рядки або числа, що дорівнюють 0 або NaN, і т.д., цикл передчасно обривається. Знову ж таки на практиці це навряд чи є проблемою для мене, але це щось, про що слід пам’ятати, що змушує цю петлю задуматися, перш ніж використовувати її… Це може дискваліфікувати її для деяких людей :)

Що мені подобається в цій петлі:

  • Це коротко писати
  • Немає необхідності отримувати доступ (властиво кешувати) властивості довжини
  • Елемент для доступу автоматично визначається в тілі циклу під вибраним вами іменем.
  • Поєднується дуже природно з array.push та array.splice для використання масивів, таких як списки / стеки

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

Для мене ця конструкція найбільше наслідує синтаксис Java 5, який мені подобається:

for (String item : someArray) {
}

... з додатковою перевагою також знати про поточний індекс всередині циклу


13
Зверніть увагу , що при такому підході цикл зупиниться , як тільки він знаходить значення falsey , такі як порожній рядок, 0, false, NaN, nullабо undefined, ще до того, iдосягає довжини, наприклад: jsfiddle.net/prvzk/1
CMS

3
Умова петлі могла бути (item=someArray[i]) !== undefined.
daniel1426

18

Існує метод ітерації тільки власних об'єктних властивостей, не включаючи прототипи:

for (var i in array) if (array.hasOwnProperty(i)) {
    // Do something with array[i]
}

але воно все одно буде перебирати задані користувачем властивості.

У JavaScript будь-яка власна властивість може бути призначена будь-якому об’єкту, включаючи масив.

Якщо ви хочете переглядати розрізнений масив, for (var i = 0; i < array.length; i++) if (i in array)або array.forEachз ним es5shimслід використовувати.


А як щодо використання for (var i in array) if (++i)?
Даніель Соколовський

15

Є кілька способів зробити це в 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>


for...inслід уникати об’єктів, схожих на масив
brk

15

Найелегантніший і швидкий спосіб

var arr = [1, 2, 3, 1023, 1024];
for (var value; value = arr.pop();) {
    value + 1
}

http://jsperf.com/native-loop-performance/8


Відредаговано (бо я помилявся)


Порівнюючи методи для циклічного перегляду масиву з 100000 елементів і щоразу робіть мінімальну операцію з новим значенням.

Підготовка:

<script src="//code.jquery.com/jquery-2.1.0.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script>
<script>
    Benchmark.prototype.setup = function() {
        // Fake function with minimal action on the value
        var tmp = 0;
        var process = function(value) {
            tmp = value; // Hold a reference to the variable (prevent engine optimisation?)
        };

        // Declare the test Array
        var arr = [];
        for (var i = 0; i < 100000; i++)
            arr[i] = i;
    };
</script>

Тести:

<a href="http://jsperf.com/native-loop-performance/16" 
   title="http://jsperf.com/native-loop-performance/16"
><img src="http://i.imgur.com/YTrO68E.png" title="Hosted by imgur.com" /></a>

Цей цикл, схоже, не відповідає порядку елементів у масиві.
Деніз Озгер

Мій тест був неправильним. Це правильно, показуючи всі LOOPS зараз. jsperf.com/native-loop-performance/16
molokoloco

@bergi має рацію. Ця петля стирає масив, коли він проходить через нього. Не те, що хочеться в більшості випадків.
Штійн де Вітт

4
перерви на предмети фальси.
njzk2

12

Оптимізований підхід полягає в кешуванні довжини масиву та використанні одного шаблону 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]
}

12

У JavaScript існує так багато рішень для циклу масиву.

Код нижче - популярні

/** Declare inputs */
const items = ['Hello', 'World']

/** Solution 1. Simple for */
console.log('solution 1. simple for')

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

console.log()
console.log()

/** Solution 2. Simple while */
console.log('solution 2. simple while')

let i = 0
while (i < items.length) {
  console.log(items[i++])
}

console.log()
console.log()

/** Solution 3. forEach*/
console.log('solution 3. forEach')

items.forEach(item => {
  console.log(item)
})

console.log()
console.log()

/** Solution 4. for-of*/
console.log('solution 4. for-of')

for (const item of items) {
  console.log(item)
}

console.log()
console.log()


12

Якщо ви хочете використовувати jQuery, у його документації є приклад:

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

12

Найкращий спосіб, на мою думку, - це використовувати функцію Array.forEach. Якщо ви не можете скористатися цим, я б запропонував отримати поліфіл з MDN. Щоб зробити його доступним, це, безумовно, найбезпечніший спосіб ітерації масиву в JavaScript.

Array.prototype.forEach ()

Отже, як підказали інші, це майже завжди те, що ви хочете:

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

Це гарантує, що все, що вам потрібно в області обробки масиву, залишається в межах цієї межі, і ви обробляєте лише значення масиву, а не властивості об'єкта та інших членів, що саме for .. робить.

Використання звичайного C-стилю for циклу в працює в більшості випадків. Важливо пам’ятати, що все, що знаходиться в циклі, розділяє свою сферу дії з рештою програми, {} не створює нової області.

Звідси:

var sum = 0;
var numbers = [1,11,22,33,44,55,66,77,88,99,111];

for(var i = 0; i<numbers.length; ++i){
  sum += numbers[i];
}

alert(i);

виведе "11" - що може бути, а може і не бути тим, що ви хочете.

Приклад робочого jsFiddle: https://jsfiddle.net/workingClassHacker/pxpv2dh5/7/


10

Це не 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
    }


1
Здається, що це може зіткнутися з аналогічними проблемами, як і для інших у звичаях з об'єктом масиву, в тому випадку, що змінні учасника прототипу також будуть спіймані для в.
Kzqai

9

Наприклад, я використовував у консолі Firefox:

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

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

Набагато чистіше ...


Це не дуже чисто в порівнянні з z.forEach(j => console.log(j));.
Sapphire_Brick

9

Коротка відповідь: так. Ви можете зробити це:

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

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

На консолі браузера можна побачити надруковані щось на кшталт "element1", "element2" тощо.


9

Ви можете використовувати Array.prototype.forEach(...):

var arr = ["apple", "banana", "cherry", "mango"];
arr.forEach((item, index)=>{
   //Some code...
});

Або Array.prototype.map(...):

var arr = ["apple", "banana", "cherry", "mango"];
arr.map((item, index)=>{
   //Some code...
});

Або jquery або для способів циклу, про які було сказано раніше.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.