Доступ к индексу элемента массива 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++;
}

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

0

ES6 for...in

for(const index in [15, 64, 78]) {                        
    console.log(index);
}

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


-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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.