Carregando...

Eventos em JavaScript

Na porta do apartamento há uma campainha. O botão é #bell e nele está escrito press. Por baixo, #chime ainda diz silent. No HTML não há atributo onclick, por isso bell.onclick começa como null.
Uma armadilha antiga: typeof null em JavaScript é "object". Logo typeof bell.onclick também é "object", não "null" nem "undefined". A comparação bell.onclick === null é verdadeira.
Pôr uma função em onclick não faz tocar. O texto fica silent até bell.click() executar a função que está no lugar. O lugar guarda uma função. Se atribuíres uma segunda, a primeira sai. Um clique não corre as duas. addEventListener é a página seguinte; ali os ouvintes empilham-se. Esta página não o chama.
bell.onclick = null esvazia o lugar. Um clique a seguir não mexe no texto. Dentro da função, this é o botão, portanto this.id é bell. A palavra do botão continua press. O script da página clica uma vez. A linha por baixo da campainha é dong / 1 / bell. Aqui não se cria um elemento nem se define uma propriedade CSS.

Um lugar no botão

A página anterior criava nós li com createElement e colocava-os com append, prepend e insertBefore. Aqui não se cria um nó nem se lê children. A página de antes escreveu style e classList numa amostra de tinta. Aqui não se atribui style. getElementById só te dá o botão e o parágrafo. A novidade é a propriedade onclick: uma função, ou null.

O que está no lugar

O botão começa com press e por baixo está silent. Lê as linhas por ordem. Cada excerto parte deste botão novo, salvo a linha da página, que é a demo de baixo. Essa demo não atribui null.

📊 O que está no lugar

Momento O que onclick guarda Texto da campainha Confusão fácil
antes de qualquer atribuição null; typeof é "object" silent ler typeof como "null"
depois da função ding, antes de click uma função silent achar que a atribuição já toca
depois de click com ding essa função ding o texto do botão passar a ding
dong substitui ding e depois um click a função dong, não ding dong as duas funções a correr
onclick = null e depois click, botão novo null; typeof é "object" silent um lugar vazio que ainda toca
script da página, um click uma função; this.id é bell dong a linha a acabar em silent

onclick é uma propriedade do elemento. Sem handler, o valor é null, e typeof null continua "object". Usa === null para saber que o lugar está vazio. A atribuição guarda a função. Não a chama. bell.click() dispara um clique e executa a função que estiver no lugar nesse momento. O texto do próprio botão não muda. Uma segunda atribuição escreve por cima da propriedade. Se guardaste um nome para a primeira função, o objeto continua na memória, mas a propriedade já não aponta para ele. onclick = null tira o handler. Um atributo HTML onclick encheria o mesmo lugar; este botão não o tem. Uma arrow function neste lugar não põe this no botão. Esta página usa uma function normal.

O lugar começa vazio

O ficheiro abre com o botão e o parágrafo. Ainda não há nada atribuído. Estas quatro saídas perguntam a propriedade, o seu typeof, o texto da campainha e a palavra do botão.

Campainha em silêncio

javascript
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
console.log(bell.onclick);
console.log(typeof bell.onclick);
console.log(chime.textContent);
console.log(bell.textContent);

As saídas são null, object, silent e press. O lugar está vazio. typeof não imprime a palavra null. O botão e o parágrafo ainda mostram as palavras da marcação.

A função espera

onclick = function ... guarda a função. O corpo não corre nessa linha. A campainha continua silent e a propriedade já não é null.

Atribuir, não tocar

javascript
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
bell.onclick = function () {
chime.textContent = "ding";
};
console.log(typeof bell.onclick);
console.log(chime.textContent);
console.log(bell.onclick === null);

As saídas são function, silent e false. Há uma função no lugar. O parágrafo não mudou, porque ninguém chamou a função.

click executa a que está lá

bell.click() executa o handler atual. A campainha passa a ding. O texto do botão fica press. Depois do clique o lugar continua com uma função.

Um clique

javascript
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
bell.onclick = function () {
chime.textContent = "ding";
};
bell.click();
console.log(chime.textContent);
console.log(bell.textContent);
console.log(typeof bell.onclick);

As saídas são ding, press e function. Um clique, uma mudança, e a mudança está no parágrafo. A palavra press continua no botão.

A segunda função substitui a primeira

Este excerto volta a começar no botão novo. Primeiro guarda-se ding, depois escreve-se dong por cima, e só então vem um click. Não há clique entre as duas atribuições, por isso nesta passagem a campainha nunca fica ding. Depois do clique fica dong. bell.onclick === ding é false. bell.onclick === dong é true.

Fica a segunda

javascript
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
function ding() {
chime.textContent = "ding";
}
function dong() {
chime.textContent = "dong";
}
bell.onclick = ding;
bell.onclick = dong;
bell.click();
console.log(bell.onclick === ding);
console.log(bell.onclick === dong);
console.log(chime.textContent);

As saídas são false, true e dong. O nome ding ainda aponta para uma função. A propriedade não. Um clique executou só dong.

null esvazia o lugar

Corre isto no botão novo. Atribui-se uma função e apaga-se antes de qualquer clique. bell.click() depois de null não escreve dong. A campainha fica silent. typeof volta a ser object, porque o valor é null.

Esvaziar o lugar

javascript
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
bell.onclick = function () {
chime.textContent = "dong";
};
bell.onclick = null;
bell.click();
console.log(bell.onclick);
console.log(typeof bell.onclick);
console.log(chime.textContent);

As saídas são null, object e silent. A função que escreveria dong não está no lugar na hora do clique. A demo de baixo não esvazia o lugar.

Uma linha por baixo da campainha

O script está no fim de body, depois do botão e do parágrafo. Guarda uma função e chama click uma vez. Dentro da função, taps passa de 0 a 1, a campainha passa a dong, e this.id é escrito em bell.dataset.who. A linha junta o texto da campainha, a contagem e esse id. Não escreve o texto do botão.

Demo da página — campainha

html
<!DOCTYPE html>
<html>
<head>
<title>events — page</title>
</head>
<body>
<button id="bell" type="button">press</button>
<p id="chime">silent</p>
<p id="line">…</p>
<script>
let bell = document.getElementById("bell");
let chime = document.getElementById("chime");
let taps = 0;
bell.onclick = function () {
taps = taps + 1;
chime.textContent = "dong";
bell.dataset.who = this.id;
};
bell.click();
document.getElementById("line").textContent =
chime.textContent + " / " + taps + " / " + bell.dataset.who;
</script>
</body>
</html>

A linha fica dong / 1 / bell. A campainha é dong, não silent. O número é 1 porque o script clica uma vez. O último pedaço é o id do botão, vindo de this dentro do handler, não a palavra press. No botão continua press. A página seguinte trata dos ouvintes de eventos. A ferramenta principal dela não é este único lugar de onclick.

Cinco verificações

  1. Lê onclick, typeof bell.onclick, o texto da campainha e o do botão. Os valores são null, object, silent e press.
  2. Atribui a função ding e não cliques. typeof é function, a campainha fica silent e onclick === null é false.
  3. Chama bell.click() com essa função ding. A campainha é ding, o botão é press e typeof é function.
  4. Atribui ding, depois dong, e faz um clique. onclick === ding é false, onclick === dong é true e a campainha é dong.
  5. Num botão novo, atribui uma função, põe onclick a null e clica. Os valores são null, object e silent. A linha da página: dong / 1 / bell.

Onde esta campainha engana

No botão continua press. No lugar estava a função errada, ou o lugar estava vazio.

  • Ler typeof bell.onclick como "null" quando o valor é null
  • Esperar que a própria atribuição ponha a campainha em ding
  • Esperar que ding e dong corram juntas num clique depois da segunda atribuição
  • Esperar que o texto do botão passe a ding
  • Esperar que click mude a campainha depois de onclick = null
  • Usar uma arrow function e esperar que this.id seja bell
  • Ler event.target aqui; estas funções não recebem argumento, e o objeto do evento fica para uma página seguinte
  • Chamar addEventListener aqui; a página seguinte empilha ouvintes
  • Construir o botão com createElement; isso era a página anterior
  • Ler a linha como silent / 0 / press

O que levas

  • Sem handler, bell.onclick é null e typeof bell.onclick é object
  • Atribuir uma função deixa a campainha silent até ao click
  • bell.click() com a função ding põe a campainha em ding e deixa o botão em press
  • A segunda atribuição substitui a primeira, por isso um clique só executa dong
  • onclick = null e depois click num botão novo deixa a campainha silent
  • A linha da página é dong / 1 / bell, e this.id dentro do handler é bell

🧠 Teste Seu Conhecimento

Pronto para Começar

Teste Seu Conhecimento

Desafie-se com este questionário interativo e veja o quão bem você entende o tópico

❓
8
Perguntas
🎯
70%
Para Passar
♾️
∞
Tempo
🔄
∞
Tentativas

📝 Instruções

  • Leia cada pergunta cuidadosamente
  • Selecione a melhor resposta para cada pergunta
  • Você pode refazer o quiz quantas vezes quiser
  • Seu progresso será mostrado no topo