Explain Codes LogoExplain Codes Logo

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

javascript
prompt-engineering
functions
callbacks
Anton ShumikhinbyAnton Shumikhin·Sep 25, 2024
TLDR

for...of, by nature, doesn't give direct access to an index, but it can be easily paired with .entries() to counter this:

for (const [index, element] of ['x', 'y', 'z'].entries()) { console.log(index, element); // Prints the index and element. Voilà! }

This results in a nifty output of index-element pairs with minimal syntax drama.

Using .entries() to your advantage

When you're in need of both the value and the index while looping, your best bet is Array.prototype.entries(). It works wonders when combined with forEach:

['a', 'b', 'c'].entries().forEach(([index, element]) => { console.log(index, element); // Juggling made easy with destructuring });

This pattern fuses forEach simplicity with index tracking power, making your life easier.

Non-array objects? No problem!

When dealing with array-like objects, using for...of directly won't cut it. That's when Object.keys() joins the party with forEach:

Object.keys(obj).forEach((key, index) => { console.log(index, obj[key]); // Hitting two birds with one stone! });

Iterating over non-array collections is a breeze despite the twisted road.

Your own enumerator

For the Python enthusiasts out there, a custom enumerate function could make your day:

function* enumerate(iterable) { let index = 0; for (const value of iterable) { yield [index++, value]; // Yep, we're manufacturing index-value pairs! } } for (const [index, value] of enumerate(['Alice', 'Bob', 'Carol'])) { console.log(index, value); // Elegantly "Pythonic" }

This is a custom-made iterator that fits in any corner of your codebase, enhancing readability.

Keeping it simple with arrow functions

If you're into simplicity, you might fancy an arrow function combined with array.forEach:

['apple', 'banana', 'cherry'].forEach((element, index) => { console.log(index, element); // Look, Mom, no hands! });

This method is intuitive, quick and fits just like an old pair of gloves.

for...in: Use with caution

Your intuition might initially lean towards using for...in with arrays, but remember, it's a different beast. Its main turf is enumerating object properties, not array elements:

for (const index in ['red', 'green', 'blue']) { if (Object.prototype.hasOwnProperty.call(array, index)) { console.log(index, array[index]); } }

This practice screams 'side effects', so it's better to stick with for...of for arrays, and treat it like a hungry bear — with respect.

The importance of the manual tracker

Counter with for...of is as basic as it gets, but don’t trip on the increment:

let index = 0; for (const val of arrayOfValues) { // Don't forget to increment index after its use, or it'll get grumpy! index++; }

Failing to increment leaves room for errors, and you might just stand up on the wrong train station.

Harmonizing with older environments

When dealing with older browsers like Internet Explorer, backwards compatibility can lead to a lot of complications. That's when you might need to polyfill Object.keys() or use other methods that promise wider net of support. Because sometimes, old is indeed gold.

Finding your way in objects

When your task is finding an index within an object, Object.keys(arr).indexOf(key) could come in handy:

const obj = { a: 'first', b: 'second' }; const index = Object.keys(obj).indexOf('b'); // Hey Sherlock, found the index! console.log('Index of b:', index); // Output: 1

This approach suits small arrays better since indexOf has to scan the whole array. No one likes exhaustive searches.

Keeping an old friend: The traditional for loop

The good ol' for loop might not be as elegant, but if you need index access, it surely is an ace up your sleeve:

for (let i = 0; i < array.length; i++) { console.log(i, array[i]); // Rock and roll, old school style! }

When you want a robust method that has both performance and index access, this never fails.

Knowing your entries

Draw a fine line between Array.entries() and Object.entries():

  • Arrays: Array.entries() provides an iterator for index-value pairs.
  • Objects: Object.entries() maps the object’s properties into key-value pairs.

Choose the right tool for the job to write efficient and well-optimized code.