Menu

for...of e for...in no JavaScript: guia prático

Entenda de vez a diferença entre for...of e for...in no JavaScript: valores x chaves, arrays x objetos e quando usar cada um.

Dois laços parecidos, funções bem diferentes

O JavaScript tem dois tipos de laço que parecem quase iguais, mas fazem coisas bem distintas. O for...of percorre os valores de um iterável. Já o for...in percorre as chaves de um objeto. Uma letrinha de diferença, um comportamento completamente diferente.

Dá pra entender a história toda com um único exemplo:

index.js
Output
Click Run to see the output here.

O primeiro loop imprime apple, banana, cherry — os valores. Já o segundo imprime 0, 1, 2 — as chaves, em forma de string. Se você escolher o errado, vai passar dez minutos se perguntando por que seu array está cheio de números.

for...of: valores de qualquer coisa iterável

O for...of é o laço que você vai usar na maior parte do tempo. Ele funciona em qualquer coisa que o JavaScript considere iterável: arrays, strings, Map, Set, NodeList, generators e por aí vai.

index.js
Output
Click Run to see the output here.

Sem ficar gerenciando índice na mão, sem scores[i]. Você pede cada valor e recebe cada valor. Strings também são iteráveis — o for...of percorre caractere por caractere:

index.js
Output
Click Run to see the output here.

Isso funciona direitinho com a maioria dos code points Unicode também, o que já é uma vantagem pequena, mas real, em relação a acessar a string por índice numérico.

Como pegar o índice no for...of

A única coisa que o for...of não te entrega de graça é a posição atual. Quando você precisa dela, é só combinar o laço com entries():

index.js
Output
Click Run to see the output here.

names.entries() devolve pares no formato [índice, valor], e a desestruturação no começo do laço já separa isso em duas variáveis. Costuma ficar bem mais limpo do que recorrer ao clássico for (let i = 0; ...) só porque você precisa do i.

for...in: percorrendo as chaves de um objeto

O for...in foi feito para objetos comuns. Ele percorre as chaves enumeráveis (strings) do objeto:

index.js
Output
Click Run to see the output here.

Repare que você recebe a chave, não o valor. Para acessar o valor, basta indexar o objeto de volta com user[key]. E tem um detalhe: toda chave vem como string — mesmo quando parece um número.

O for...in também percorre a cadeia de protótipos, ou seja, pode acabar expondo propriedades herdadas. Em objetos literais do seu próprio código isso raramente incomoda, mas quando você itera sobre instâncias de uma classe ou objetos vindos de alguma biblioteca, vale a pena se proteger:

index.js
Output
Click Run to see the output here.

Object.hasOwn(user, key) ignora qualquer coisa herdada. Em código moderno, a maioria das pessoas evita usar for...in e prefere Object.keys, Object.values ou Object.entries — o que nos leva direto para a próxima seção.

A forma moderna de percorrer um objeto em JavaScript

Em vez de for...in, combine for...of com um dos helpers Object.*. É só escolher qual dos três encaixa melhor no que você precisa:

index.js
Output
Click Run to see the output here.

Object.entries fica especialmente gostoso de ler — desestruturar o par [chave, valor] soa quase como texto em português. E, como esses métodos devolvem só as propriedades próprias enumeráveis do objeto, você não precisa se preocupar com lixo herdado do prototype.

Evite for...in em arrays

Até funciona, tecnicamente, mas é cilada na certa:

index.js
Output
Click Run to see the output here.

Você recebe 0, 1, 2 e tag. Qualquer propriedade que alguém tenha adicionado ao array — ou ao Array.prototype via polyfill — também aparece. As chaves são strings, então key + 1 faz concatenação no lugar de soma. E a ordem de iteração não é garantida em todos os casos extremos.

Regrinha prática:

  • Só os valores do array? for...of arr.
  • Índice e valor do array? for...of arr.entries().
  • Só o índice, contando? O clássico for (let i = 0; i < arr.length; i++).
  • Chaves ou entradas de um objeto? Object.keys(obj) / Object.entries(obj) combinados com for...of.

Resumindo: o for...in é ferramenta de nicho. O for...of junto com os helpers de Object resolve tudo que você precisa no dia a dia.

break e continue funcionam nos dois

Os dois laços aceitam os recursos habituais para sair mais cedo:

index.js
Output
Click Run to see the output here.

continue pula para a próxima iteração; break sai do laço de uma vez. Esse é o principal motivo para preferir for...of em vez de .forEach() — dentro do callback do forEach não dá para usar break, mas no for...of dá numa boa.

Resumo lado a lado

index.js
Output
Click Run to see the output here.

Quatro laços, quatro propósitos, e um único modelo mental: se você quer os valores de algo iterável, use for...of. Se precisa mexer com as propriedades de um objeto, passe por Object.keys / Object.values / Object.entries — também com for...of. Já o for...in fica reservado para aquele caso raro em que você realmente precisa de todas as chaves string enumeráveis de um objeto, herdadas ou não.

A seguir: valores truthy e falsy

Todo if e todo laço em JavaScript acaba fazendo a mesma pergunta por baixo dos panos: esse valor é considerado verdadeiro? E a resposta nem sempre é óbvia — strings vazias, o zero, null e undefined se comportam de formas bem diferentes do que você imagina. No próximo tópico, vamos entender os valores truthy e falsy.

Perguntas frequentes

Qual a diferença entre for...of e for...in no JavaScript?

O for...of percorre os valores de algo iterável, como array, string, Map ou Set. Já o for...in percorre as chaves (nomes das propriedades) de um objeto. Num array ['a', 'b'], o for...of devolve 'a' e 'b'; o for...in devolve '0' e '1' — como strings.

Dá pra usar for...of direto num objeto?

Direto não — objetos comuns não são iteráveis. O jeito é usar Object.keys(obj), Object.values(obj) ou Object.entries(obj) pra gerar um array e aí sim iterar com for...of. O padrão mais comum é for (const [key, value] of Object.entries(obj)).

Por que evitar for...in em arrays?

Até funciona, mas o for...in passa por toda propriedade enumerável, inclusive as herdadas e qualquer coisa que alguém tenha adicionado em Array.prototype. Além disso, as chaves vêm como string e a ordem nem sempre é garantida. Prefira for...of pros valores, ou o for clássico quando precisar do índice.

Aprenda a programar com o Coddy

COMEÇAR