[javascript] Get loop counter/index using for…of syntax in JavaScript

Caution:

question still applies to for…of loops.> Don't use for…in to iterate over an Array, use it to iterate over the properties of an object. That said, this


I understand that the basic for…in syntax in JavaScript looks like this:

for (var obj in myArray) {
    // ...
}

But how do I get the loop counter/index?

I know I could probably do something like:

var i = 0;
for (var obj in myArray) {
    alert(i)
    i++
}

Or even the good old:

for (var i = 0; i < myArray.length; i++) {
    var obj = myArray[i]
    alert(i)
}

But I would rather use the simpler for-in loop. I think they look better and make more sense.

Is there a simpler or more elegant way?


In Python it's easy:

for i, obj in enumerate(myArray):
    print i

This question is related to javascript for-loop foreach counter

The answer is


for…in iterates over property names, not values, and does so in an unspecified order (yes, even after ES6). You shouldn’t use it to iterate over arrays. For them, there’s ES5’s forEach method that passes both the value and the index to the function you give it:

var myArray = [123, 15, 187, 32];

myArray.forEach(function (value, i) {
    console.log('%d: %s', i, value);
});

// Outputs:
// 0: 123
// 1: 15
// 2: 187
// 3: 32

Or ES6’s Array.prototype.entries, which now has support across current browser versions:

for (const [i, value] of myArray.entries()) {
    console.log('%d: %s', i, value);
}

For iterables in general (where you would use a for…of loop rather than a for…in), there’s nothing built-in, however:

function* enumerate(iterable) {
    let i = 0;

    for (const x of iterable) {
        yield [i, x];
        i++;
    }
}

for (const [i, obj] of enumerate(myArray)) {
    console.log(i, obj);
}

demo

If you actually did mean for…in – enumerating properties – you would need an additional counter. Object.keys(obj).forEach could work, but it only includes own properties; for…in includes enumerable properties anywhere on the prototype chain.


Here's a function eachWithIndex that works with anything iterable.

You could also write a similar function eachWithKey that works with objets using for...in.

// example generator (returns an iterator that can only be iterated once)
function* eachFromTo(start, end) { for (let i = start; i <= end; i++) yield i }

// convers an iterable to an array (potential infinite loop)
function eachToArray(iterable) {
    const result = []
    for (const val of iterable) result.push(val)
    return result
}

// yields every value and index of an iterable (array, generator, ...)
function* eachWithIndex(iterable) {
    const shared = new Array(2)
    shared[1] = 0
    for (shared[0] of iterable) {
        yield shared
        shared[1]++
    }
}

console.log('iterate values and indexes from a generator')
for (const [val, i] of eachWithIndex(eachFromTo(10, 13))) console.log(val, i)

console.log('create an array')
const anArray = eachToArray(eachFromTo(10, 13))
console.log(anArray)

console.log('iterate values and indexes from an array')
for (const [val, i] of eachWithIndex(anArray)) console.log(val, i)

The good thing with generators is that they are lazy and can take another generator's result as an argument.


How about this

let numbers = [1,2,3,4,5]
numbers.forEach((number, index) => console.log(`${index}:${number}`))

Where array.forEach this method has an index parameter which is the index of the current element being processed in the array.


That's my version of a composite iterator that yields an index and any passed generator function's value with an example of (slow) prime search:

_x000D_
_x000D_
const eachWithIndex = (iterable) => {_x000D_
  return {_x000D_
    *[Symbol.iterator]() {_x000D_
      let i = 0_x000D_
      for(let val of iteratable) {_x000D_
        i++_x000D_
          yield [i, val]_x000D_
      }_x000D_
    }_x000D_
  }_x000D_
_x000D_
}_x000D_
_x000D_
const isPrime = (n) => {_x000D_
  for (i = 2; i < Math.floor(Math.sqrt(n) + 1); i++) {_x000D_
    if (n % i == 0) {_x000D_
      return false_x000D_
    }_x000D_
  }_x000D_
  return true_x000D_
}_x000D_
_x000D_
let primes = {_x000D_
  *[Symbol.iterator]() {_x000D_
    let candidate = 2_x000D_
    while (true) {_x000D_
      if (isPrime(candidate)) yield candidate_x000D_
        candidate++_x000D_
    }_x000D_
  }_x000D_
}_x000D_
_x000D_
for (const [i, prime] of eachWithIndex(primes)) {_x000D_
  console.log(i, prime)_x000D_
  if (i === 100) break_x000D_
}
_x000D_
_x000D_
_x000D_


In ES6, it is good to use for - of loop. You can get index in for of like this

for (let [index, val] of array.entries()) {
        // your code goes here    
}

Note that Array.entries() returns an iterator, which is what allows it to work in the for-of loop; don't confuse this with Object.entries(), which returns an array of key-value pairs.


For-in-loops iterate over properties of an Object. Don't use them for Arrays, even if they sometimes work.

Object properties then have no index, they are all equal and not required to be run through in a determined order. If you want to count properties, you will have to set up the extra counter (as you did in your first example).

loop over an Array:

var a = [];
for (var i=0; i<a.length; i++) {
    i // is the index
    a[i] // is the item
}

loop over an Object:

var o = {};
for (var prop in o) {
    prop // is the property name
    o[prop] // is the property value - the item
}

Solution for small array collections:

for (var obj in arr) {
    var i = Object.keys(arr).indexOf(obj);
}

arr - ARRAY, obj - KEY of current element, i - COUNTER/INDEX

Notice: Method keys() is not available for IE version <9, you should use Polyfill code. https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/keys


To use for..of loop on array and retrieve index you can you use array1.indexOf(element) which will return the index value of an element in the loop. You can return both the index and the value using this method.

_x000D_
_x000D_
array1 = ['a', 'b', 'c']
for (element of array1) {
    console.log(array1.indexOf(element), element) // 0 a 1 b 2 c
}
_x000D_
_x000D_
_x000D_


As others have said, you shouldn't be using for..in to iterate over an array.

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

If you want cleaner syntax, you could use forEach:

myArray.forEach( function ( val, i ) { ... } );

If you want to use this method, make sure that you include the ES5 shim to add support for older browsers.


Answer Given by rushUp Is correct but this will be more convenient

for (let [index, val] of array.entries() || []) {
   // your code goes here    
}

On top of the very good answers everyone posted I want to add that the most performant solution is the ES6 entries. It seems contraintuitive for many devs here, so I created this perf benchamrk.

enter image description here

It's ~6 times faster. Mainly because doesn't need to: a) access the array more than once and, b) cast the index.


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to for-loop

List append() in for loop Prime numbers between 1 to 100 in C Programming Language Get current index from foreach loop how to loop through each row of dataFrame in pyspark TypeScript for ... of with index / key? Is there a way in Pandas to use previous row value in dataframe.apply when previous value is also calculated in the apply? Python for and if on one line R for loop skip to next iteration ifelse How to append rows in a pandas dataframe in a for loop? What is the difference between ( for... in ) and ( for... of ) statements?

Examples related to foreach

Angular ForEach in Angular4/Typescript? How to use forEach in vueJs? Python foreach equivalent Get current index from foreach loop TypeScript for ... of with index / key? JavaScript: Difference between .forEach() and .map() JSON forEach get Key and Value Laravel blade check empty foreach Go to "next" iteration in JavaScript forEach loop Why is "forEach not a function" for this object?

Examples related to counter

HTML/Javascript Button Click Counter How to sort Counter by value? - python How to count the number of words in a sentence, ignoring numbers, punctuation and whitespace? Counter increment in Bash loop not working Get loop counter/index using for…of syntax in JavaScript Count characters in textarea Counter in foreach loop in C# jQuery counter to count up to a target number How to count the frequency of the elements in an unordered list? Code for a simple JavaScript countdown timer?