Closed ElaineDelgado closed 2 years ago
Olá @ElaineDelgado.
Passando para dizer que visualizei a issue e se estiver tudo ok com a aplicação, em breve a análise será postada aqui =)
Olá @ElaineDelgado!
Parabéns pelo esforço em construir a primeira aplicação do treinamento =)
Saber onde declarar const, se dentro ou fora da função;
Um princípio que gosto de seguir é: deixe as declarações das suas variáveis perto de onde elas são usadas.
Porém, nem sempre esse princípio deve ser aplicado. Por questões de escopo.
Um exemplo clássico é quando vc tem duas funções que precisam acessar a mesma variável.
No código abaixo, func1 e func2 acessam myConst normalmente:
const myConst = 'my value'
const func1 = () => {
console.log(myConst)
}
const func2 = () => {
console.log(myConst)
}
func1() // 'my value'
func2() // 'my value'
Porém, se myConst é declarada dentro de func1, func2 não consegue acessar myConst por que myConst agora é acessível apenas dentro do escopo de func1:
const func1 = () => {
const myConst = 'my value'
console.log(myConst)
}
const func2 = () => {
console.log(myConst)
}
func1() // 'my value'
func2() // app.js:7 Uncaught ReferenceError: myConst is not defined
Esse é um caso onde myConst precisa estar em escopo global, para que ela seja acessada dentro das duas funções.
Mais à frente, vc começará a ver por que variáveis globais não são uma boa ideia. Mas por enquanto, isso não é importante.
Um outro caso que vc precisa considerar é o escopo de bloco...
Lembra que não há problema em duas consts de mesmo nome serem criadas em escopos diferentes?
No código abaixo,
const myFunc = () => {
const myConst = 'my value'
console.log(myConst)
}
myFunc()
myFunc()
a cada vez que myFunc
é invocada, o bloco que contém a declaração da const e o console.log é executado, certo?
Blocos criam escopos.
Isso significa que na primeira vez que myFunc foi invocada, um escopo com a const myConst foi criado. E na segunda vez em que ela foi invocada, um outro escopo com uma outra const myConst foi criado.
Ou seja, se myFunc
é invocada 2x, duas consts myConst
foram criadas em memória.
E isso é importante pelo seguinte...
Copie o código abaixo e execute ele:
<div></div>
<button>Adicionar parágrafo</button>
const div = document.querySelector('div')
const button = document.querySelector('button')
const paragraph = document.createElement('p')
button.addEventListener('click', () => {
div.appendChild(paragraph)
})
Ao executar esse código e clicar no botão pela primeira vez, vc verá que um <p>
fio adicionado dentro da <div>
.
Porém, do segundo clique em diante, não são adicionados novos <p>
.
Por que isso acontece?
Isso acontece por que a cada execução do callback de clique, o paragraph
ao invés de ser criado novamente está apenas sendo reaproveitado.
Ou seja, como paragraph
foi declarado fora do escopo do callback, a cada execução do bloco do callback, o mesmo parágrafo está sendo inserido dentro da div.
Lembre-se: quando um callback de listener de evento é executado, ele não faz o código que está fora dele ser declarado novamente. Apenas o bloco do callback é executado novamente. Isso significa que o mesmo paragraph
está sendo usado dentro do callback.
Agora, se paragraph
for declarado dentro do callback,
button.addEventListener('click', () => {
const paragraph = document.createElement('p')
div.appendChild(paragraph)
})
toda vez que esse bloco do callback for executado, um novo paragraph
será criado em memória e inserido como filho da div. Ou seja, o segundo clique no botão irá inserir um segundo <p>
como filho da div, um terceiro clique irá inserir um terceiro <p>
e assim por diante. Graças ao escopo de bloco =)
Ficou mais claro?
Refatorar o código, sempre acho que a legibilidade está boa.
De fato, o ideal é não refatorar apenas por refatorar.
Porém, legibilidade e dinamicidade podem andar juntas.
O código abaixo é legível, porém, repetitivo:
const userAnswers = [
form.anime1.value,
form.anime2.value,
form.anime3.value,
form.anime4.value,
form.anime5.value,
form.anime6.value,
form.anime7.value,
form.anime8.value,
form.anime9.value,
form.anime10.value,
]
Nas aulas seguintes, vc verá como eliminar repetições como essa =)
Vou deixar abaixo alguns pontos, segundo os critérios que usei para analisar.
Você entendeu que não era necessário manipular DOM dentro do forEach
(um erro comum que algumas pessoas cometem). A ideia do forEach
ali naquele momento era apenas calcular os pontos, exatamente como vc fez =)
O parâmetro do callback do forEach
foi nomeado de forma coerente, como singular de itens do array no qual o forEach
foi encadeado.
Você deixou claro o total de pontos que o quiz tem na mensagem "Você fez ${totalScore} pontos de 100!". Isso é bom para a usabilidade, pq traz clareza do progresso do usuário no quiz.
No geral, você escolheu nomes descritivos para suas variáveis e funções.
Algumas alternativas estão com o valor do atributo value
trocado. Por exemplo, na 1ª pergunta, a segunda alternativa tem o value recebendo 3 e a terceira tem o value recebendo 2. Isso pode deixar a aplicação imprevisível devido à ser presumido naturalmente que o value de cada alternativa corresponde à posição dela.
Observe que se vc descer até a última pergunta, verá que a primeira alternativa está marcada por padrão. Porém, se vc marcar a alternativa 1 da antepenúltima pergunta, verá que agora a última pergunta não tem mais a primeira alternativa marcada. Isso aconteceu devido a conflitos de marcação HTML, onde o valor de id
ou name
não correspondem ao for
correto da label em questão.
Talvez, depois de você hospedar o quiz no Netlify (como orientado na bateria de exercícios 20), alguém execute a aplicação no celular. Nesse caso, é preciso ficar atenta ao o local onde a pontuação é exibida na tela.
Imagina que, por algum motivo, o usuário não visualizou a parte inferior ao botão de envio. No print abaixo, após enviar o form, a pontuação é exibida na parte inferior (não-visível) da tela:
Uma possível solução seria exibir os pontos em um local em que o usuário está olhando no momento do envio. Poderia ser, por exemplo, logo acima do botão "enviar" =)
E claro, nas aulas seguintes você verá uma forma de implementar os pontos.
A const btnVoltarInicio
está em pt-BR enquanto o restante das variáveis está em inglês. O ideal é que apenas um idioma seja usado =)
Um princípio que gosto de seguir ao nomear é:
getName
, setName
, incrementCounter
;user
, score
, color
. is
, has
ou should
. isOdd
, hasSevenItems
, shouldUpdate
.Considerando isso...
totalScorePoints
é uma função que foi nomeada como substantivo. showScore
é um verbo que pode descrever com mais clareza o que essa função faz.
Nas aulas seguintes, você verá formas de refatorar o código dessa aplicação.
Mais uma vez, parabéns pelo esforço =)
As observações fizeram sentido?
Bom dia, professor! Sim, a explicação fez bastante sentido. Em relação à lógica onde o senhor diz: ". Porém, se vc marcar a alternativa 1 da antepenúltima pergunta, verá que agora a última pergunta não tem mais a primeira alternativa marcada. " Isso foi um erro meu no html, realmente, o "id" e o "name" estão com valor"anime8" em vez de "anime10". Falta de atenção minha. E em relação ao "Algumas alternativas estão com o valor do atributo value trocado. " , foi intencional pois se eu colocasse na ordem, todas as perguntas teriam a teriam a terceira opção como correta, não consegui pensar em uma forma de deixar os "value" em ordem mas na aplicação trocar a ordem das alternativas corretas.
Muito obrigada pelas explicações!!
não consegui pensar em uma forma de deixar os "value" em ordem mas na aplicação trocar a ordem das alternativas corretas
O ponto principal está no array correctAnswers
.
Mas antes de chegar nele, preciso que vc execute o passo passo abaixo comigo, ok?
Copie e execute o código abaixo:
<form>
<h2>Pergunta</h2>
<div>
<label>
<input type="radio" name="inputQuestion1" value="1">
Alternativa 1
</label>
</div>
<div>
<label>
<input type="radio" name="inputQuestion1" value="2" checked>
Alternativa 2
</label>
</div>
<div>
<label>
<input type="radio" name="inputQuestion1" value="3">
Alternativa 3
</label>
</div>
</div>
</form>
Vc verá que a alternativa 2 da pergunta está marcada. E ela está marcada por que o atributo checked
foi inserido nela. Se o clique acontecer em outra alternativa, o input correspondente recebe o atributo checked
, correto?
Imagine que no momento em que o form foi enviado, a alternativa 2 foi marcada como a alternativa correta.
Então de alguma forma, vc precisa, no seu código js, obter qual das 3 alternativas foi marcada como a correta, certo?
Observe que os 3 inputs da alternativa contém name="inputQuestion1"
. Eles tem esse atributo pq os 3 estão relacionados à pergunta 1. Se houvesse uma pergunta 2, os inputs dessa pergunta teriam name="inputQuestion2"
.
Para saber qual alternativa da pergunta está marcada no momento do envio, basta especificar form.inputQuestion1.value
:
const form = document.querySelector('form')
console.log(form.inputQuestion1.value) // 2
Ou seja, a expressão form.inputQuestion1.value
resulta no valor do atributo value
do input que contém o atributo checked
.
Como vc sabe que a alternativa correta é a que está marcada (2), é fácil fazer uma comparação que ative a soma de pontos ao usuário:
const form = document.querySelector('form')
let score = 0
if (form.inputQuestion1.value === '2') {
score = 10
}
console.log(score) // 10
Só que imagina que ao invés de uma pergunta, houvessem 10.
Como vc vai dizer, no seu código js, qual é a alternativa correta de cada pergunta?
É aqui que entra o array correctAnswers
.
Se a alternativa correta da pergunta 1 é a que contém o value do input armazenando 2, o primeiro item do array será 2:
const form = document.querySelector('form')
const correctAnswers = ['2']
let score = 0
if (form.inputQuestion1.value === correctAnswers[0]) {
score = 10
}
console.log(score) // 10
Se a alternativa correta da pergunta 2 é a que contém o value do input armazenando 3, o segundo item do array será 3. Então ficaria const correctAnswers = ['2', '3']
.
Ficou mais claro?
@ElaineDelgado
Ficou bem claro, sim. Não tinha pensado em colocar elementos diferentes na array correctAnswers, faz mais sentido que ordenar aleatoriamente no HTML. Muito obrigada, professor!
Show! No que precisar, é só abrir uma nova issue. Rumo à fluência! 🔥
As cores da sua versão da aplicação são diferentes das cores da aplicação mostrada na aula?
Sim
A aplicação contém funcionalidades que não foram mostradas nas aulas?
Não
A aplicação contém features da linguagem que não foram mostradas nas aulas?
Não
Link do repositório da aplicação
https://github.com/ElaineDelgado/quizCJRM
Maiores dificuldades durante a implementação
Saber onde declarar const, se dentro ou fora da função; Refatorar o código, sempre acho que a legibilidade está boa.
Menores dificuldades durante a implementação
Lógica do app, Implementação do código funcional; HTML e CSS, Bootstrap.