1. javascript
  2. /references
  3. /for-in-loop

The for...in Loop in JavaScript

When it comes to loops in JavaScript, the for...in loop is a versatile iteration method that allows us to iterate over the properties of an object.

However, it has a few quirks that we need to be aware of, so let's dive in and explore them.

Take a look at the basic syntax of a for...in loop:

for (const property in object) {
  console.log(property);
}

The for...in loop will iterate over all countable properties of an object, including those inherited from its prototypes. Consequently, this can lead to unexpected results if we're not careful. To avoid this, we can use Object.hasOwnProperty() to check if a property is attached directly to the object and not its prototypes.

for...in Loop Examples

Let's take a look at a few practical examples.

Consider the following object:

const cheetah = {
    kingdom: "Animalia",
    family: "Felidae",
    order: "Carnivora"
}

Logging the Properties

Here's how you would use the for...in loop to log the properties of the cheetah object:

for (const property in cheetah) {
  console.log(property);
}

Output result:

kingdom
family
order

Logging the Values

You can also use the for...in loop to log the values of the properties in an object:

for (const property in cheetah) {
  console.log(cheetah[property]);
}

The output would result in:

Animalia
Felidae
Carnivora

Logging Both Keys and Values

Now, we'll combine both the keys and values of the cheetah object and log them together:

const cheetah = {
    kingdom: "Animalia",
    family: "Felidae",
    order: "Carnivora"
}

for (const property in cheetah) {
  console.log(`${property}: ${cheetah[property]}`);
}

// Output
// kingdom: Animalia
// class: Mammalia
// order: Carnivora

Accessing Nested Properties with String Manipulation

Observe the following nested object structure:

const animal = {
  name: "Lion",
  scientificName: "Panthera leo",
  habitat: {
    continent: "Africa",
    region: "Savanna"
  },
  characteristics: {
    coat: "golden",
    roar: "loud"
  },
  diet: ["antelopes", "zebras", "buffaloes"]
}

Now, let's access and manipulate the data, including converting the value properties to uppercase:

for (const property in animal) {
  if (typeof animal[property] === "string") {
    console.log(`${property}: ${animal[property].toUpperCase()}`);
  } else if (Array.isArray(animal[property])) {
    console.log(`${property}: ${animal[property].join(", ").toUpperCase()}`);
  } else {
    console.log(`${property}:`);
    for (const nestedProperty in animal[property]) {
      console.log(`  ${nestedProperty}: ${animal[property][nestedProperty].toUpperCase()}`);
    }
  }
}

The Final Output:

name: LION
scientificName: PANTHERA LEO
habitat:
  continent: AFRICA
  region: SAVANNA
characteristics:
  coat: GOLDEN
  roar: LOUD
diet: ANTELOPES, ZEBRAS, BUFFALOES

Using console.dir() to Debug

Iteration with the for...in loop can be a bit tricky, especially when it comes to unexpected results due to properties inherited from prototypes.

We can utilize the console.dir() method to inspect an object and see all its properties, including the inherited ones:

console.dir(animal);

The output in the console will be an interactive tree-like structure enabling us to inspect the properties of an object and potentially locate unexpected inclusions.

Additional Resources

The for Loop

The for...of Loop

The While Loop

The do...while Variation

Break and Continue in JavaScript

A Guide to JavaScript Object Methods