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

228

Мы можем получить доступ к элементам массива, используя цикл for:

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

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

Абденнур ТУМИ
источник

Ответы:

351

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

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

Если вы хотите получить доступ и к ключу, и к значению, вы можете использовать Array.prototype.entries()с деструктуризацией :

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

Михал Перлаковский
источник
64
В случае , если кто - то чудеса, я испытал for-ofс , .entries()и это в два раза медленнее по сравнению с .forEach(). jsperf.com/for-of-vs-foreach-with-index
1
@ K48 приятно знать, используйте «обратный цикл», если вы хотите иметь самый быстрый в es: incredible-web.com/blog/…
nimo23
3
К сожалению, мне нужно уступить из вложенного цикла. Невозможно использовать forEach, поскольку функция создает проблемы с областью действия для yieldключевого слова. Но мне нужен доступ к индексу для моего варианта использования, так что ... ;;я думаю , что это простой старый цикл.
Кайл Бейкер
2
@KyleBaker А что не так с циклом for .entires()?
Михал Перлаковский
1
Вместо обратного цикла вы можете кешировать длину jsperf.com/reverse-loop-vs-cache . Полезно для итеративной обработки, когда вы можете обрабатывать поток без создания больших массивов в оперативной памяти. Скорость цикла не будет узким местом, так как в таких случаях у вас будет задержка ввода / вывода.
x'ES
289

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

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

}
Феликс Клинг
источник
3
С TypeScript: «TS2495: Тип IterableIterator не является типом массива или типом строки». Похоже, это будет решено: github.com/Microsoft/TypeScript/pull/12346
Йоханнес
2
Также Internet Explorer не поддерживается.
Сэмми
1
Не хорошо. Выдает ошибку, например, с помощью document.styleSheets[0].cssRules.entries()даже или, document.styleSheets.entries()возможно, многих других итеративных структур DOM. Еще надо использовать _.forEach()сlodash
Стивен Прибилинский
2
@ Steven: Если вам не нужен индекс, вы можете просто сделать for (var value of document.styleSheets) {}. Если вам нужен индекс вы можете преобразовать значение в массив первым с помощью Array.from: for (let [index, value] of Array.from(document.styleSheets)) {}.
Феликс Клинг
1
Это мило! Array.fromтакое FTW
Стивен Прибилинский
28

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

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

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

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

Крис
источник
1
Ага. Хороший, понятный и простой. О, и так у вас есть супер простой способ доступа к ключу / индексу массива.
Объединить
2
Кстати, условие должно выглядеть так -> для (пусть i = 0; i <arr.length; i ++) без (-1), иначе оно не будет зацикливаться во всех элементах массива.
Объединить
1
@Combine Хороший улов! Я обновил свой ответ, чтобы отразить вашу заметку.
Крис
4
Вы все еще можете и гораздо легче читать. Вернуться назад так же просто, как добавить . breakfor-offor (let [index, value] of array.entries()).reverse()
Найджел Б. Пек
3
Я думаю, что это вполне приемлемый ответ на этот вопрос. Это никогда не будет принятым ответом, но это помогло нескольким дюжинам людей или больше, которые искали этот вопрос. Вот для чего ТАК.
Данорам
3

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

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

    element.innerHTML = '#' + index

}
Джозеф Мердриньяк
источник
Да, это работает, тогда как другие, упомянутые выше @Steven Прибилинским, другие методы DOM возвращают объекты, у которых нет entriesметода для них.
Матенстер
3

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

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

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

Виллем ван дер Веен
источник
3

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

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

  i++;
}
TintinSansYeux
источник
0

Для тех , кто использует объекты , которые не являются 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))
Hashbrown
источник
0

ES6 for...in

for(const index in [15, 64, 78]) {                        
    console.log(index);
}
Solanki ...
источник
5
Вопрос задается о for...ofпетле, а не оfor...in
Авраам Эрнандес
3
for...inявляется частью оригинальной спецификации ECMAScript (то есть "es1"). Также обратите внимание, что for...inон предназначен для перебора свойств объекта. Хотя он может перебирать массивы, он может делать это не в ожидаемом порядке. См. Больше в документации MDN
Боаз
0

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

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

Saksham
источник
-6
var fruits = ["apple","pear","peach"];
for (fruit of fruits) {
    console.log(fruits.indexOf(fruit));
    //it shows the index of every fruit from fruits
}

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

Эдвин Фелипе
источник
2
Это займет О (п ^ 2) время.
Гарри
3
В случаях, когда производительность не важна, это все еще не дает все правильные индексы, когда есть повторяющиеся фрукты. Например, для ["apple", "apple", "pear"]приведенных индексов 0, 0, 2вместо 0, 1, 2.
Trichoplax