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

Parametro event nomeando a função

Não sei o que está errado

botao.addEventListener("click",adiciona(event));

function adiciona(event){
  event.preventDefault();
  alert("oi clicou");
}
Uncaught TypeError: Cannot read property 'preventDefault' of undefined

Se uso como função anomima dá certo.

4 respostas
solução!

Jaime, boa noite!

Repare nessa linha:

botao.addEventListener("click",adiciona(event));

Você tem um botao, ele é um objeto. Mais especificamente, um elemento do DOM (representação da página HTML).

O objeto botao possui um método/função chamado addEventListener, o qual você acessou por meio do ponto (.).

Quando você abre e fecha parênteses nesse método/função, significa que você está chamando/executando essa função.

No caso do addEventListener, ele aceita receber 2 argumentos (na verdade até 4, mas os 2 últimos são opcionais). O primeiro argumento deve ser uma string que representa o tipo de evento a ser ouvido. O segundo argumento deve ser uma função (pode ser um objeto, mas envolve outros detalhes), que vai ser executada quando o evento for emitido.

Bem, como eu disse, quando você abre e fecha parênteses depois do nome de uma função, você está a executando.

Repare novamente na chamada, mas agora foque no segundo argumento que você passou:

addEventListener("click",adiciona(event));

O segundo argumento que você passou não é uma função. É na verdade a chamada de uma função, ou seja, primeiro essa função vai ser executada, vai te retornar um valor e vai colocar esse valor como segundo argumento, pra ficar mais claro, supondo que a função adiciona retorne o valor 10. No final das contas o interpretador JavaScript faria isso:

addEventListener("click", 10);

O que você quer fazer na verdade é passar a função como argumento, então simplesmente não a chame (não abra e feche parênteses):

addEventListener("click",adiciona);

Agora sim, quando o evento for disparado, sua função será chamada. Quanto ao event, o próprio navegador que vai passar ele pra sua função.

Quanto ao erro que aconteceu, você chamou a função (adiciona(event)), mas de onde você está tirando esse event? Você não criou nenhuma variável event nesse escopo. Isso significa que quando a função adiciona é executada, ela recebe o valor undefined como argumento. E aí você tenta acessar o método preventDefault dentro do event, mas event não é um objeto neste caso, ele é undefined, ou seja, não possui o método preventDefault.

Cannot read property 'preventDefault' of undefined
Não é possível ler a propriedade 'preventDefault' de undefined

Eu cheguei a responder uma dúvida parecida, mas que envolve alguns outros conceitos, se tiver curiosidade, dê uma olhada: https://cursos.alura.com.br/forum/topico-chamando-um-funcao-dentro-de-outra-funcao-46891

Perfeito Pedro!!

Ok, entendi a diferença entre passar a função como objeto(que só será executado quando ocorrer o evento) ou como valor que seria o resultado da execução da função que será o parametro.

É que eu achava que como a função espera receber o paramentro event, eu teria que invocar essa função passando esse parametro na sua chamada também.

Consertando o código ficaria assim então:

botao.addEventListener("click",adiciona); // nao precisa enviar o parametro event

function adiciona(event){   // a função recebe um parametro que eu não passei, esse foi o nó que deu na minha cabeça kkk
  event.preventDefault();  
  alert("oi clicou");
}

A minha confusão foi essa, a função recebe um parametro que não passei. Neste caso é porque o parametro event, sempre que declarado como parametro na função, quem chamar essa função, já passa ela automaticamente, ou seja o event é uma característica do javascrpit ?

  1. Sim, a função espera receber event, mas você não tem um event pra passar pra ela.
  2. Não, o argumento event não vai ser sempre passado pra uma função que tenha declarado que aceita recebê-lo, até porque uma função pode aceitar receber qualquer coisa como argumento, o nome não importa.
  3. Esse objeto event que é passado para sua função não é uma característica do JavaScript. Quem cuida disso é o navegador.

No navegador, eventos estão acontecendo (sendo disparados) a todo instante: quando uma página termina de carregar, quando uma tecla do teclado é pressionada, quando o ponteiro do mouse passa por cima de elementos, etc.

Eventos são objetos com várias propriedades, são informações sobre uma ação que ocorreu dentro do navegador. Por exemplo, em um evento de click, o navegador cria um objeto event que vai ter informações como: coordenadas da tela onde o click aconteceu (event.screenX / event.screenY), o elemento que foi alvo do click (event.target), entre outos.

Estes eventos são disparados em elementos do DOM, DOM é a sigla para Document Object Model (Modelo de objeto de documento), ou seja, é uma representação em memória, e em objeto, de uma página HTML. Cada nó desse objeto é um elemento da página representado como objeto. É exatamente por isso que você consegue fazer botao.addEventListener, addEventListener é uma das propriedades do elemento do DOM que você guardou na variável botao.

Veja a seguinte página em HTML:


<html>
  <head>
  </head>

  <body>
    <button id="botao">Meu Botão</button>
  </body>
</html>

É muito mais complexo, mas tente imaginar que o DOM é simplesmente um objeto que a representa dessa maneira:


window = {

  document: {

    childNodes: {

      0: {

        localName: "html",
        childNodes: {

          0: { localName: "head" },
          1: {

            localName: "body",

            childNodes: {

              0: {
                localName: "button",
                id: "botao",
                innerText: "Meu Botão",
                addEventListener: function () {}
              }

            }

          }

        }

      }
    }

  }

}

Coloquei a propriedade addEventListener no elemento 0 que representa o botão, para ficar mais simples de entender, no entanto a propriedade addEventListener não está ali. Justamanete por ser uma função que é igual pra vários elementos do DOM, ela está em um outro objeto, neste caso os elementos do DOM delegam a responsabilidade de chamar essa função para esse objeto.

Esse objeto que possui a função addEventListener é um objeto EventTarget (alvo de evento). Ele também possui as funções removeEventListener e dispatchEvent.

Muitos elementos do DOM delegam para este objeto, por isso podemos dizer que estes elementos também são EventTarget's, isso é um pouco parecido com o conceito de herança em outras linguagens orientadas a objetos, como Java e C#.

No exemplo do botão, um elemento button é um EventTarget, por isso você pode adicionar ouvidores de eventos a ele, remover ouvidores de eventos, e despachar eventos a partir dele.

No site da Mozilla, há um exemplo de implementação do objeto EventTarget.

A função addEventListener basicamente cria um array para o tipo de evento que você passou pra ela, e guarda a sua função ouvidora nesse array.

Veja a função dispatchEvent:


EventTarget.prototype.dispatchEvent = function(event) {
  if (!(event.type in this.listeners)) {
    return true;
  }
  var stack = this.listeners[event.type];

  for (var i = 0, l = stack.length; i < l; i++) {
    stack[i].call(this, event);
  }
  return !event.defaultPrevented;
};

Veja que essa função recebe um event como argumento, ela basicamente irá passar pelo array de ouvidores (funções que foram previamente adicionadas como ouvidoras deste elemento), e executará essas funções ouvidoras, passando pra elas o mesmo event que ela havia recebido como argumento.

Então esse é o cara que passa o event pra sua função.

Mas quem passou o event pra dispatchEvent? O navegador. É uma lógica implementada pelo navegador que quando um evento acontecer ele cria um objeto de evento e dispara o evento ocorrido usando a função dispathcEvent. Nesse momento os ouvidores serão executados e receberão event.

E se você achar necessário (mas acredito que isso não costuma acontecer muito) você pode criar seus eventos e despachá-los em um momento, caso você tenha adicionado ouvidores a este evento, eles serão executados. Se tiver interesse dê uma olhada na página Creating and triggering events da Mozilla.