Como iterar objetos no JavaScript

20/09/2021
Rafael
JS
Como iterar objetos no JavaScript

Para percorrer arrays podemos utilizar laços de repetições, como o for ou o while, por exemplo. Mas, se tratando de objetos, como fazemos isso? Aqui vão algumas alternativas:

for...in

Segundo a nossa amiga mdn, a definição de for...in é a seguinte:

O laço for...in interage sobre propriedades enumeradas de um objeto, na ordem original de inserção. O laço pode ser executado para cada propriedade distinta do objeto.

Vamos fazer um teste:

  const goty = {
    2015: 'The Witcher 3: Wild Hunt',
    2016: 'Overwatch',
    2017: 'The Legend of Zelda: Breath of the Wild',
    2018: 'God of War',
    2019: 'Sekiro: Shadows Die Twice',
    2020: 'The Last of Us Part II'
  };

  for (let prop in goty) {
    console.log(`${prop}: ${goty[prop]}`);
  }

  // output:
  // 2015: The Witcher 3: Wild Hunt
  // 2016: Overwatch
  // 2017: The Legend of Zelda: Breath of the Wild
  // 2018: God of War
  // 2019: Sekiro: Shadows Die Twice
  // 2020: The Last of Us Part II

Porém, caso o prototype seja modificado, as alterações também serão exibidas:

  Object.prototype.foo = function () {
    console.log('bar');
  }

  const goty = {
    2015: 'The Witcher 3: Wild Hunt',
    2016: 'Overwatch',
    2017: 'The Legend of Zelda: Breath of the Wild',
    2018: 'God of War',
    2019: 'Sekiro: Shadows Die Twice',
    2020: 'The Last of Us Part II'
  };

  for (let prop in goty) {
    console.log(`${prop}: ${goty[prop]}`);
  }

  // output:
  // 2015: The Witcher 3: Wild Hunt
  // 2016: Overwatch
  // 2017: The Legend of Zelda: Breath of the Wild
  // 2018: God of War
  // 2019: Sekiro: Shadows Die Twice
  // 2020: The Last of Us Part II
  // foo: function () {
  //   console.log('bar');
  // }

Para evitar que as propriedades herdadas sejam mostradas, devemos fazer uma verificação usando o método hasOwnProperty():

  Object.prototype.foo = function () {
    console.log('bar');
  }

  const goty = {
    2015: 'The Witcher 3: Wild Hunt',
    2016: 'Overwatch',
    2017: 'The Legend of Zelda: Breath of the Wild',
    2018: 'God of War',
    2019: 'Sekiro: Shadows Die Twice',
    2020: 'The Last of Us Part II'
  };

  for (let prop in goty) {
    if (goty.hasOwnProperty(prop)) {
      console.log(`${prop}: ${goty[prop]}`);
    }
  }

  // output:
  // 2015: The Witcher 3: Wild Hunt
  // 2016: Overwatch
  // 2017: The Legend of Zelda: Breath of the Wild
  // 2018: God of War
  // 2019: Sekiro: Shadows Die Twice
  // 2020: The Last of Us Part II

Agora sim, obtemos o resultado esperado.

Object.keys()

Outra estratégia para iterar um objetos é transformá-lo em array e o método Object.keys() faz exatamente isso: ele cria um array de strings com as chaves do objeto. Dessa forma, basta percorrer o array retornado:

  const goty = {
    2015: 'The Witcher 3: Wild Hunt',
    2016: 'Overwatch',
    2017: 'The Legend of Zelda: Breath of the Wild',
    2018: 'God of War',
    2019: 'Sekiro: Shadows Die Twice',
    2020: 'The Last of Us Part II'
  };

  const keys = Object.keys(goty);

  keys.forEach(key => {
    console.log(`${key}: ${goty[key]}`)
  });

  // output:
  // 2015: The Witcher 3: Wild Hunt
  // 2016: Overwatch
  // 2017: The Legend of Zelda: Breath of the Wild
  // 2018: God of War
  // 2019: Sekiro: Shadows Die Twice
  // 2020: The Last of Us Part II

Object.entries()

Este método nos retorna um array com as chaves e os valores do objeto. No entanto, ele está em fase experimental, então é recomendado checar sua compatibilidade antes de usá-lo em produção.

  const goty = {
    2015: 'The Witcher 3: Wild Hunt',
    2016: 'Overwatch',
    2017: 'The Legend of Zelda: Breath of the Wild',
    2018: 'God of War',
    2019: 'Sekiro: Shadows Die Twice',
    2020: 'The Last of Us Part II'
  };

  const entries = Object.entries(goty);

  entries.forEach(([key, value]) => {
    console.log(`${key}: ${value}`);
  });

  // output:
  // 2015: The Witcher 3: Wild Hunt
  // 2016: Overwatch
  // 2017: The Legend of Zelda: Breath of the Wild
  // 2018: God of War
  // 2019: Sekiro: Shadows Die Twice
  // 2020: The Last of Us Part II