Categories
JavaScript Best Practices

JavaScript Antipatterns —Loops

Spread the love

JavaScript lets us do a lot of things. It’s sometimes too forgiving in its syntax.

In this article, we’ll look at some antipatterns that we should avoid when we write JavaScript loops.

for Loops

for loops are handy for iterating over arrays and array-like objects.

For instance, we can write:

const arr = [1, 2, 3];
for (let i = 0; i < arr.length; i++) {
  // do something with arr[i]
}

This loops the indexes of the arr array and let us do something with each entry.

It also works with array-like objects. Nodelists are array-like objects.

We can call the following methods to get a Nodelist with multiple DOM elements:

  • document.querySelectorAll()
  • document.getElementsByName()
  • document.getElementsByClassName()
  • document.getElementsByTagName()

document.querySelectorAll() is the most versatile since it accepts any CSS selector.

document.getElementsByName only returns the items with the given name attribute.

document.getElementsByClassName only returns the items with the given class name.

document.getElementsByTagName returns items with the given tag name.

Also, the following properties of the document have specific items

  • document.images — all img elements on a page
  • document.links — all a elements
  • document.forms — all forms
  • document.forms[0].elements — all fields in a form

We can loop through them as follows:

for (let i = 0; i < document.links.length; i++) {
  // do something with document.links[i]
}

With the for loop, we can define all the initial conditions in the first expression, so we can write:

for (let i = 0, max = arr.length; i < max; i++) {
  // do something with arr[i]
}

which is the same as:

for (let i = 0; i < arr.length; i++) {
  // do something with arr[i]
}

i++ is the same as i = i + 1 or i += 1 .

i++ can be tricky if we assign it to something.

i++ returns the original value of i instead of the updated value.

So if we have:

let i = 1;
const a = i++;

We get that a is 1.

for-in Loops

for-in loops are useful for looping through keys of an object and its prototypes.

Therefore, if we only want to loop through the object’s non-inherited keys, we’ve to use the hasOwnProperty method.

For instance, we can use it by writing:

const obj = {
  a: 1,
  b: 2
}

for (const key in obj) {
  if (obj.hasOwnProperty(key)) {
    //...
  }
}

That will only loop through the keys that are non-inherited as hasOwnProperty checks that.

We can also call hasOwnProperty as follows:

const obj = {
  a: 1,
  b: 2
}

for (const key in obj) {
  if (Object.prototype.hasOwnProperty.call(obj, key)) {
    //...
  }
}

This will avoid issues when the obj object redefined hasOwnProperty to be something else.

We can also write:

const obj = {
  a: 1,
  b: 2
}

const hasOwn = Object.prototype.hasOwnProperty;
for (const key in obj) {
  if (hasOwn.call(obj, key)) {
    //...
  }
}

to cache the hasOwnProperty method.

for-of Loop

The for-of loop is more versatile than the other loops. It’s useful for looping through the arrays and array-like objects.

So it’s a great alternative to the for loop for looping through those objects.

It also works with all the document properties listed above and also new data structures like sets and maps.

We can use it as follows:

for (const link of document.links) {
  // do something with link
}

For arrays, we can write:

for (const a of arr) {
  // do something with a
}

It also works with the destructuring assignment syntax:

for (const { foo, bar } of arr) {
  // do something with foo and bar
}

It also works great with sets and maps:

for (const s of set) {
  // do something with a
}

For maps, we can write:

const map = new Map([
  ['a', 1],
  ['b', 2]
])

for (const [key, value] of map) {
  // do something with key and value
}

Conclusion

A for loop is great for looping through arrays and array-like objects.

However, the for-loop beats that by letting us loop through any iterable object.

The for-in loop has limited uses for looping through keys in an object. If we want to loop through their prototype’s keys as well, then we can use that.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *