Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

[Dúvida] Dúvida de um erro no console

Antes de iniciar essa aula eu tentei fazer os sons tocarem dinamicamente mas estava acontecendo um erro que eu nao entendi o porque. Eu estava tentando fazer desse jeito:

const teclas = document.querySelectorAll('.tecla');
let index = 0;

function playSound(idSound){
    document.querySelector('#som_' + idSound).play();
}

while(index < teclas.length){

    teclas[index].onclick = function () {
        playSound(teclas[index].classList[1]);
    };

    index++;
}

só que no console aparecia um esse erro: Insira aqui a descrição dessa imagem para ajudar na acessibilidade

depois que fiz uma const dentro do while, como a professora fez na aula, o codigo funcionou. Alguem sabe dizer porque não posso fazer direto sem ter que criar uma const?

2 respostas
solução!

O problema que você está enfrentando tem a ver com o conceito de "closures" (fechamentos) em JavaScript. Vou explicar o que está acontecendo no código e o motivo pelo qual o uso de uma const dentro do loop resolve o problema.

No código original, você está usando um loop while para percorrer todas as teclas e adicionar um evento de clique a cada uma delas. No entanto, o evento de clique está chamando a função playSound passando o valor do index como argumento. O index é uma variável que está sendo incrementada a cada iteração do loop e, quando a função playSound é executada, ela usará o valor atual de index.

O problema é que, quando ocorre um clique em uma das teclas, a função playSound é chamada, mas o valor do index já foi incrementado para o número total de teclas (ou seja, teclas.length). Portanto, a função playSound sempre recebe o mesmo valor para idSound, que é o valor de teclas[teclas.length].classList[1], o que provavelmente não existe, gerando o erro que você viu no console.

Para resolver esse problema, a alternativa com o uso de uma const dentro do loop é uma forma de criar um escopo separado para cada iteração do loop. Ao fazer isso, o valor do index é capturado como uma cópia dentro do escopo da constante, e cada função de clique criada dentro do loop terá acesso a esse valor específico.

Aqui está o exemplo corrigido usando uma const dentro do loop:

const teclas = document.querySelectorAll('.tecla');

function playSound(idSound) {
    document.querySelector('#som_' + idSound).play();
}

for (let index = 0; index < teclas.length; index++) {
    teclas[index].onclick = function () {
        playSound(teclas[index].classList[1]);
    };
}

Ao usar let index = 0, o index é criado como uma variável de bloco no escopo do loop for, e cada iteração terá um valor diferente para index. Isso evita o problema de closure e faz com que o código funcione corretamente.

Muito obrigado pela explicação Francisco