Доступ к индексу элемента массива ES6 внутри цикла for-of

Мы можем получить доступ к элементам массива с помощью цикла for-of:

for (const j of [1, 2, 3, 4, 5]) {
  console.log(j);
}

Как я могу изменить этот код, чтобы получить доступ к текущему индексу? Я хочу добиться этого, используя синтаксис for-of, ни forEach, ни for-in.


person Abdennour TOUMI    schedule 18.12.2015    source источник


Ответы (12)


Используйте Array.prototype.keys:

for (const index of [1, 2, 3, 4, 5].keys()) {
  console.log(index);
}

Если вы хотите получить доступ и к ключу, и к значению, вы можете использовать _ 3_ с деструктуризацией :

for (const [index, value] of [1, 2, 3, 4, 5].entries()) {
  console.log(index, value);
}

person Michał Perłakowski    schedule 18.12.2015
comment
Если кому-то интересно, я тестировал for-of с .entries(), и он вдвое медленнее, чем .forEach(). jsperf.com/for-of-vs-foreach-with-index - person ; 25.09.2017
comment
@ K48 приятно знать, используйте обратный цикл for, если вы хотите иметь самый быстрый в es: incredible-web.com/blog/ - person nimo23; 15.01.2018
comment
К сожалению, мне нужно уступить изнутри вложенного цикла. Невозможно использовать forEach, потому что функция создает проблемы с областью для ключевого слова yield. Но мне нужен доступ к индексу для моего варианта использования, так что ... я думаю, это базовый старый цикл ;;. - person Kyle Baker; 10.02.2018
comment
@KyleBaker А что не так с циклом for-of с .entires()? - person Michał Perłakowski; 10.02.2018
comment
Я предполагаю, что это также не было бы эффективным, но в этом, конечно, не было бы необходимости. Вы можете использовать его, если хотите, но природа стандартного цикла for такова, что он имеет очень простой «доступ» как к индексу, так и к значению. При использовании for-of потребуется .entries(), чтобы иметь доступ к индексу. - person Kyle Baker; 10.02.2018
comment
Вместо обратного цикла вы можете кэшировать длину jsperf.com/reverse-loop-vs-cache . For-of полезно для итеративной обработки, когда вы можете обрабатывать поток без создания больших массивов в ОЗУ. Скорость цикла не будет узким местом, поскольку в таких случаях у вас будет задержка ввода-вывода. - person x'ES; 19.02.2018
comment
Работает ли это, даже если мы циклически включаем HTMLCollection? - person Rickyx; 17.06.2020

Array#entries возвращает индекс и значение, если вам нужны оба :

for (let [index, value] of array.entries()) {

}
person Felix Kling    schedule 18.12.2015
comment
С TypeScript: «TS2495: Type IterableIterator не является типом массива или строковым типом». Похоже, это будет решено: github.com/Microsoft/TypeScript/pull/12346 - person Johannes; 08.03.2017
comment
Также не поддерживается Internet Explorer. - person Sammi; 24.03.2017
comment
Не хорошо. Выдает ошибку, например с document.styleSheets[0].cssRules.entries() или даже document.styleSheets.entries() и, вероятно, многими другими итеративными структурами DOM. По-прежнему нужно использовать _.forEach() из lodash - person Steven Pribilinskiy; 07.06.2017
comment
@Steven: Если вам не нужен индекс, вы можете просто сделать for (var value of document.styleSheets) {}. Если вам нужен индекс, вы можете сначала преобразовать значение в массив через Array.from: for (let [index, value] of Array.from(document.styleSheets)) {}. - person Felix Kling; 08.06.2017
comment
Это мило! Array.from - это FTW - person Steven Pribilinskiy; 11.06.2017
comment
Вместо того, чтобы жаловаться на то, какие браузеры что поддерживают, напишите на ES6 и перенесите на ES5. Напиши один раз, СУХОЙ, ПОЦЕЛУЙ ... - person pmont; 20.06.2017

В этом мире ярких новых нативных функций мы иногда забываем об основах.

for (let i = 0; i < arr.length; i++) {
    console.log('index:', i, 'element:', arr[i]);
}

Чисто, эффективно, и вы все еще можете break зацикливаться. Бонус! Вы также можете начать с конца и вернуться назад с помощью i--!

Дополнительное примечание: если вы часто используете значение в цикле, вы можете сделать const value = arr[i]; в верхней части цикла для удобной и удобочитаемой ссылки.

person chris    schedule 26.09.2018
comment
Ага. Хороший, простой и понятный. О, и вот так у вас есть очень простой способ получить доступ к ключу / индексу массива. - person Combine; 10.10.2018
comment
Между прочим, условие должно выглядеть так - ›for (let i = 0; i‹ arr.length; i ++) без (-1), иначе оно не будет повторяться по всем элементам массива. - person Combine; 10.10.2018
comment
@Combine Хороший улов! Я обновил свой ответ, чтобы отразить вашу заметку. - person chris; 11.10.2018
comment
Вы все еще можете break a for-of и for (let [index, value] of array.entries()) гораздо легче читать. Вернуться назад так же просто, как добавить .reverse(). - person ; 28.10.2018
comment
Это никоим образом не отвечает на вопрос. Было бы неплохо в комментарии (всегда важны основы), но не здесь. - person user3658510; 11.10.2019
comment
Я не думаю, что это отвечает на конкретный вопрос, но вы совершенно правы, что это хороший способ сделать это. - person Filip Cordas; 11.10.2019
comment
Думаю, это вполне приемлемый ответ на этот вопрос. Это никогда не будет общепринятым ответом, но он помог нескольким десяткам или более человек, которые искали этот вопрос. Это то, для чего нужна SO. - person Danoram; 11.10.2019
comment
Простой цикл for примерно в 8 раз быстрее, чем for of array.entries(). jsbench.me/6dkh13vqrr/1 - person Henrique Bruno; 03.11.2020

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

let i = 0;
for (const item of iterableItems) {
  // do something with index
  console.log(i);

  i++;
}
person TintinSansYeux    schedule 27.01.2020

В цикле for..of мы можем добиться этого с помощью array.entries(). array.entries возвращает новый объект-итератор Array. Объект-итератор знает, как получить доступ к элементам из итерируемого в конкретный момент времени, отслеживая при этом свое текущее положение в этой последовательности.

При вызове метода next() для итератора создаются пары значений ключа. В этих парах ключ-значение массив index является ключом, а элемент массива - значением.

let arr = ['a', 'b', 'c'];
let iterator = arr.entries();
console.log(iterator.next().value); // [0, 'a']
console.log(iterator.next().value); // [1, 'b']

Цикл for..of - это, по сути, конструкция, которая использует итерацию и перебирает все элементы (используя итератор под капотом). Мы можем объединить это с array.entries() следующим образом:

array = ['a', 'b', 'c'];

for (let indexValue of array.entries()) {
  console.log(indexValue);
}


// we can use array destructuring to conveniently
// store the index and value in variables
for (let [index, value] of array.entries()) {
   console.log(index, value);
}

person Willem van der Veen    schedule 27.09.2018

в контексте html / js, в современных браузерах, с другими повторяемыми объектами, кроме массивов, мы также могли бы использовать [Iterable] .entries ():

for(let [index, element] of document.querySelectorAll('div').entries()) {

    element.innerHTML = '#' + index

}
person Joseph Merdrignac    schedule 12.12.2017
comment
Да, это работает, тогда как другие, упомянутые выше @Steven Pribilinskiy, другие методы DOM возвращают объекты, для которых нет метода entries. - person matanster; 24.01.2019

Другой подход может заключаться в использовании Array.prototype.forEach() в качестве

Array.from({
  length: 5
}, () => Math.floor(Math.random() * 5)).forEach((val, index) => {
  console.log(val, index)
})

person Saksham    schedule 27.01.2020

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

let index = 0;

а затем используйте оператор присваивания добавления в объем цикла

index += 1;

Вот и все, проверьте приведенный ниже пример фрагмента.

let index = 0;
for (const j of [1, 2, 3, 4, 5]) {
  index += 1;
  console.log('index ',index);
}

person Hidayt Rahman    schedule 01.04.2021

Для тех, кто использует объекты, которые не являются Array или даже похожими на массивы, вы можете легко создать свою собственную итерацию, чтобы вы по-прежнему могли использовать for of для таких вещей, как localStorage, которые на самом деле имеют только length:

function indexerator(length) {
    var output = new Object();
    var index = 0;
    output[Symbol.iterator] = function() {
        return {next:function() {
            return (index < length) ? {value:index++} : {done:true};
        }};
    };
    return output;
}

Затем просто введите число:

for (let index of indexerator(localStorage.length))
    console.log(localStorage.key(index))
person Hashbrown    schedule 12.07.2018

Также вы можете использовать JavaScript для решения вашей проблемы.

iterate(item, index) {
    console.log(`${item} has index ${index}`);
    //Do what you want...
}

readJsonList() {    
    jsonList.forEach(this.iterate);
    //it could be any array list.
}   

person Ivan Nascimento Feliciano    schedule 20.10.2020

const fruits = ["apple","pear","peach"];
for (fruit of fruits) {
    // TODO remove before commit to avoid decrease of performance
    const i = fruits.indexOf(fruit);
    console.log(i)
    //it shows the index of every fruit from fruits, should be used only on development and debug process 
}

Цикл for просматривает массив, а свойство indexof принимает значение индекса, соответствующего массиву. П.Д. у этого метода есть недостатки с числами, поэтому используйте фрукты.

person Edwin Felipe    schedule 13.09.2018
comment
Это занимает время O (n ^ 2). - person Harry; 16.12.2018
comment
В случаях, когда производительность не важна, это все равно не дает всех правильных индексов при наличии повторяющихся фруктов. Например, для ["apple", "apple", "pear"] указаны индексы 0, 0, 2 вместо 0, 1, 2. - person trichoplax; 24.03.2019
comment
Я думаю, что это не должно быть отклонено, но требует объяснения. Это увеличивает сложность, поэтому его не следует использовать в производстве. Но его можно использовать при разработке или отладке на консоли для тестирования конкретных сценариев и в тех случаях, когда я не хочу использовать записи, которые будут постоянными модификациями. - person Pablo Palacios; 18.03.2021

person    schedule
comment
Вопрос касается for...of цикла, а не for...in - person abranhe; 15.05.2019
comment
for...in является частью исходной спецификации ECMAScript (т.е. es1). Также обратите внимание, что for...in предназначен для перебора свойств объекта. Хотя он может перебирать массивы, он может делать это не в ожидаемом порядке. Дополнительную информацию см. В документации MDN - person Boaz - CorporateShillExchange; 25.12.2019