Pegadinha #1 de entrevistas em JavaScript

Pegadinha #1 de entrevistas em JavaScript

Tulio Faria
Tulio Faria7 de novembro de 2017
Hoje quero comentar uma questão muito comum em entrevistas de JavaScript.
Qual é a saída desse código?

const arr = ['a', 'b', 'c', 'd'] for (var i = 0; i < arr.length; i++) { setTimeOut(() => { console.log(i, arr[i]) }, 0) } console.log('out', i)

Detalhe que estamos utilizando um setTimeOut com um zero, mas poderia ser qualquer valor.
O primeiro detalhe é que percebemos que o out saiu primeiro com o número 4. O 'var' foi definido dentro do for, porém eu consegui dar um console log lá é baixo. Podemos chegar a conclusão que ele não respeitou o escopo. Outro ponto importante é que ele aconteceu antes do restante, isso acontece porque sempre que utilizamos o setTimeOut, ele leva essa execução da arrow function para dentro do event loop.
Como o i já está com 4, ele não é um número válido, pois nosso array inicia-se em zero e termina em 3. Por esse motivo virá o seguinte:

out 4 4 undefined 4 undefined 4 undefined 4 undefined

Como arrumamos essa função?
Temos algumas formas de arrumar isso. Existe uma bem simples e algumas que podemos brincar um pouco mais.
A primeira bem simples é trocar o var por let:

for (let i=0; i<arr.length; i++){ setTimeOut(() => { console.log(i, arr[i]) },0)

Agora funcionou perfeitamente:

0 'a' 1 'b' 2 'c' 3 'd'

Por que essa diferença?
Quando estamos com o var, seria equivalente a quando ele estiver executando o código ele puxa todos os vars pra cima, isso é conhecido como hoisting.
Por esse motivo, sempre que possível, utilize let e const.
Outra maneira seria transformar em setTimeOut em uma maneira que eu consiga injetar as variáveis dentro dele mesmo, como uma self invoked:

setTimeOut( (function (ii) { return () => { console.log(ii, arr[ii]) } })(i), 0 )

Iremos executar a função e a partir da function o ii vai estar válido. Assim funcionará também do jeito que esperávamos.
Confira o video:
ODBoaezEfMo
Assistir vídeo
Curta o DevPleno no Facebook, se inscreva no canal no YouTube e cadastre seu e-mail para não perder as atualizações. Abraço!
Tulio Faria
Autor
Tulio Faria7 de novembro de 2017

Últimas do Blog