## DEV Community

Maxi Contieri

Posted on • Updated on • Originally published at maximilianocontieri.com

# Code Smell 53 - Explicit Iteration

We learned loops back in school. But enumerators and iterators are the next generation.

TL;DR: Don't use indices while iterating. Prefer Higher level collections.

# Problems

• Encapsulation

• Declarativeness

# Solutions

1. Favor foreach() or high order iterators

2. You will be able to use yield(), caches, proxies, lazy loading and much more when you hide your implementation details.

# Sample Code

## Wrong

``````for (i = 0; i < colors.count(), i++) {
print(colors[i]);
}
``````

## Right

``````foreach (color of colors) {
print(color);
}

//Closures and arrow functions
colors.foreach(color => print(color));
``````

# Detection

Linters can find this smell using regex.

There might be false positives. See exceptions below.

# Exceptions

If the problem domain needs the elements to be bijected to natural numbers like indices, the first solution is adequate.

Remember all time to find real world analogies.

• Declarative

# Conclusion

This kind of smell do not ring the bell to many developers because they think this is a subtlety.

Clean code is full of this few declarative things that can make a difference.

# Credits

Photo by Elena Mozhvilo on Unsplash

If you get tired of writing for loops, take a break and continue later.

David Walker

Last update: 2021/06/13

The Right JS code is kind of wrong syntax wise and stuff. This would be the correct code:

``````
for (color in colors) {
print(colors[color]);
}

//Closures and arrow functions
colors.foreach(color => console.log(color);
``````

Michel Descoteaux • Edited

Or in this case it could have been simplified even further to:

``````for (color of colors) {
console.log(color);
}

//Closures and arrow functions
colors.forEach(color => console.log(color));
``````

Patrik Jajcay
``````colors.forEach(console.log);
``````

Maxi Contieri

Nice!

Buğra Hasbek

I don't use js and this confused the hell out of me at first sight :) i was expecting color to be an element in colors but it is used as an index? I think I prefer the c++ way

``````for (auto color:colors)
print(color);
``````

Pacharapol Withayasakpunt
• Depends on the programming language; but JavaScript `in` is damn confusing.
• A closing bracket is missing at the end.

1. Yeah, unless they wanted to print keys (including inherited), they should have used `of` not `in`.
2. a closing parenthesis*

Maxi Contieri

corrected! thank you!

Pacharapol Withayasakpunt

I also prefer to hide explicit iteration. Still, I had to use the first style for chunking.

``````const batchSize = 500

for (let i = 0; i < items.length; i += batchSize) {
await batchInsert(items.slice(i, i + batchSize))
}
``````

The second style (`for ... of`) is for awaiting inside, or `for await ... of`.

The third style, I generally use `map` because of performance, but grammatically, it would be for each. Also, `map(async () => ...)` can be used with `Promise.all` (or `Promise.allSettled`).

Maxi Contieri

In my opinion chinking should be hidden at iteration level.

Pacharapol Withayasakpunt • Edited

That is, if a convenient library function exists.

Mihail Malo
1. You want to use `of` with iterators, `in` is for string keys of objects (including inherited).
2. `for in` and `for of` syntax in js looks like `for (const ident of expression)` (where `const` could be `let` or `var` and `of` could be `in`)
3. there's a missing `)` in the last statement
4. most commonly available print fn in js is `console.log`
5. `Array` method is called `forEach` (capitalization)

so, all in all:

``````const colors = ['red', 'green']
const {log} = console

for (const color of colors)
log(color)

// closure/arrow function
colors.forEach(color => log(color))
``````

if for some reason you have to use `in` to iterate over values of an object, it's typically done like this (to avoid iterating over inherited keys)

``````for (const key in obj)
if (obj.hasOwnProperty(key))
do_thing(key, dict[key])
``````

however you should prefer the new iterators, such as `Object.keys()`, `Object.values()` and `Object.entries()`.
As such, the above becomes:

``````for (const [key, val] of Object.entries(obj))
do_thing(key, val)
``````

Finally, if you see yourself operating on keys of an Object generically like this, you might instead be looking for Map, which naturally iterates by "entries", and supports non-string keys.

``````const ref = {two: 2}
const m = new Map([[1, "val1"], [ref, "val2"]])
for (const [k,v] of m)
console.log("key", k, "value", v)
``````

Maxi Contieri

Wow!

How many detaill!

Nevertheless i use many different languages on all my code smells and i like to think them as pseudo code without entering any language details. Your solution is clearly a better one but it is too tied to a particular language.

Mihail Malo

What other languages do you use?

Maxi Contieri

see my code smells

up to now:
javascript
pyhton
php
golang
java
ruby

Language is accidental
Code smells are not related to any particular language

I write code snippets as examples but I think them most as pseudocode