Ambos estão corretos, mas nenhum deles é "melhor" por si só, e pode haver um motivo para o desenvolvedor escolher usar as duas abordagens.
Ouvintes de Eventos (addEventListener e attachEvent do IE)
As versões anteriores do Internet Explorer implementam o javascript de maneira diferente de praticamente qualquer outro navegador. Com versões menores que 9, você usa o método attachEvent
[ doc ], assim:
element.attachEvent('onclick', function() { /* do stuff here*/ });
Na maioria dos outros navegadores (incluindo o IE 9 e superior), você usa addEventListener
[ doc ], assim:
element.addEventListener('click', function() { /* do stuff here*/ }, false);
Usando essa abordagem ( eventos DOM Nível 2 ), você pode anexar um número teoricamente ilimitado de eventos a qualquer elemento. A única limitação prática é a memória do lado do cliente e outras preocupações de desempenho, que são diferentes para cada navegador.
Os exemplos acima representam o uso de uma função anônima [ doc ]. Você também pode adicionar um ouvinte de evento usando uma referência de função [ doc ] ou um encerramento [ doc ]:
var myFunctionReference = function() { /* do stuff here*/ }
element.attachEvent('onclick', myFunctionReference);
element.addEventListener('click', myFunctionReference , false);
Outra característica importante addEventListener
é o parâmetro final, que controla como o ouvinte reage a eventos de bolhas [ doc ]. Passei falso nos exemplos, o que é padrão para provavelmente 95% dos casos de uso. Não há argumento equivalente para attachEvent
, ou ao usar eventos embutidos.
Eventos embutidos (HTML onclick = "" propriedade e element.onclick)
Em todos os navegadores que suportam javascript, você pode colocar um ouvinte de eventos em linha, o que significa diretamente no código HTML. Você provavelmente já viu isso:
<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>
Os desenvolvedores mais experientes evitam esse método, mas ele faz o trabalho; é simples e direto. Você não pode usar encerramentos ou funções anônimas aqui (embora o próprio manipulador seja uma espécie de função anônima) e seu controle do escopo seja limitado.
O outro método que você menciona:
element.onclick = function () { /*do stuff here */ };
... é o equivalente a javascript embutido, exceto que você tem mais controle do escopo (já que está escrevendo um script em vez de HTML) e pode usar funções anônimas, referências de função e / ou fechamentos.
A desvantagem significativa dos eventos embutidos é que, diferentemente dos ouvintes de eventos descritos acima, você pode ter apenas um evento embutido atribuído. Eventos embutidos são armazenados como um atributo / propriedade do elemento [ doc ], o que significa que ele pode ser substituído.
Usando o exemplo <a>
do HTML acima:
var element = document.getElementById('testing');
element.onclick = function () { alert('did stuff #1'); };
element.onclick = function () { alert('did stuff #2'); };
... quando você clica no elemento, você vê apenas "Did stuff # 2" - você substituiu o primeiro atribuído da onclick
propriedade pelo segundo valor e também substituiu a onclick
propriedade HTML embutida original . Confira aqui: http://jsfiddle.net/jpgah/ .
De um modo geral, não use eventos embutidos . Pode haver casos de uso específicos, mas se você não tiver 100% de certeza de que possui esse caso de uso, não precisará e não deverá usar eventos em linha.
Javascript moderno (angular e similares)
Desde que esta resposta foi postada originalmente, as estruturas javascript como Angular tornaram-se muito mais populares. Você verá um código como este em um modelo Angular:
<button (click)="doSomething()">Do Something</button>
Parece um evento embutido, mas não é. Esse tipo de modelo será transpilado para um código mais complexo que usa ouvintes de eventos nos bastidores. Tudo o que escrevi sobre eventos aqui ainda se aplica, mas você é removido do âmago da questão por pelo menos uma camada. Você deve entender as porcas e os parafusos, mas se as práticas recomendadas da estrutura JS moderna envolvem a gravação desse tipo de código em um modelo, não sinta que você está usando um evento embutido - não está.
Qual é melhor?
A questão é uma questão de compatibilidade e necessidade do navegador. Você precisa anexar mais de um evento a um elemento? Você vai no futuro? As probabilidades são, você vai. attachEvent e addEventListener são necessários. Caso contrário, um evento em linha pode parecer que eles resolveriam o problema, mas você está muito melhor preparado para um futuro que, embora possa parecer improvável, é previsível pelo menos. Há uma chance de você precisar mudar para ouvintes de eventos baseados em JS, então é melhor começar por aí. Não use eventos embutidos.
O jQuery e outras estruturas javascript encapsulam as diferentes implementações de navegador dos eventos do nível DOM 2 em modelos genéricos, para que você possa escrever código compatível com o navegador sem ter que se preocupar com a história do IE como rebelde. O mesmo código com o jQuery, todo o navegador e pronto para o rock:
$(element).on('click', function () { /* do stuff */ });
Porém, não se esgote e obtenha uma estrutura apenas para isso. Você pode facilmente rolar seu próprio pequeno utilitário para cuidar dos navegadores mais antigos:
function addEvent(element, evnt, funct){
if (element.attachEvent)
return element.attachEvent('on'+evnt, funct);
else
return element.addEventListener(evnt, funct, false);
}
// example
addEvent(
document.getElementById('myElement'),
'click',
function () { alert('hi!'); }
);
Experimente: http://jsfiddle.net/bmArj/
Levando tudo isso em consideração, a menos que o script que você está vendo tenha levado em consideração as diferenças do navegador de outra maneira (no código não mostrado na sua pergunta), a parte usada addEventListener
não funcionaria nas versões do IE inferiores a 9.
Documentação e Leitura Relacionada
function addEvent(element, myEvent, fnc) { return ((element.attachEvent) ? element.attachEvent('on' + myEvent, fnc) : element.addEventListener(myEvent, fnc, false)); }
function addEvent(e,n,f){return e.attachEvent?e.attachEvent('on'+n,f):e.addEventListener(n,f,!!0)}
<< Com 98 caracteres, este é mais do que 40% menor!A diferença que você poderia ver se tivesse outras funções:
As funções 2, 3 e 4 funcionam, mas 1 não. Isso ocorre porque
addEventListener
não substitui os manipuladores de eventos existentes, enquantoonclick
substitui osonclick = fn
manipuladores de eventos existentes .A outra diferença significativa, é claro, é que
onclick
sempre funcionará, enquantoaddEventListener
não funciona no Internet Explorer antes da versão 9. Você pode usar o análogoattachEvent
(que tem sintaxe um pouco diferente) no IE <9.fonte
Nesta resposta, descreverei os três métodos de definição de manipuladores de eventos DOM.
element.addEventListener()
Exemplo de código:
Mostrar snippet de código
element.addEventListener()
tem várias vantagens:element.removeEventListener()
.useCapture
parâmetro, que indica se você deseja manipular o evento em sua fase de captura ou bolha . Consulte: Não é possível entender o atributo useCapture em addEventListener ..onevent
propriedades de elementos DOM, muitos programadores JavaScript inexperientes pensam que o nome do evento é por exemploonclick
ouonload
.on
é não uma parte do nome do evento . Os nomes de eventos corretos sãoclick
eload
, e é assim que os nomes dos eventos são passados.addEventListener()
.element.onevent = function() {}
(por exemploonclick
,onload
)Exemplo de código:
Mostrar snippet de código
Essa era uma maneira de registrar manipuladores de eventos no DOM 0. Agora é desencorajado, porque:
onevent
propriedade de volta ao seu estado inicial (ou sejanull
).window.onload
, por exemplo:,window.onload = "test";
ela não emitirá erros. Seu código não funcionaria e seria muito difícil descobrir o porquê..addEventListener()
no entanto, geraria um erro (pelo menos no Firefox): TypeError: O argumento 2 do EventTarget.addEventListener não é um objeto .Manipuladores de eventos embutidos (
onevent
atributo HTML)Exemplo de código:
Mostrar snippet de código
Da mesma forma
element.onevent
, agora é desencorajado. Além dos problemas queelement.onevent
tem, ele:Content-Security-Policy
cabeçalho HTTP adequado para bloquear scripts embutidos e permitir scripts externos apenas de domínios confiáveis. Vejo Como a política de segurança de conteúdo funciona?Veja também
EventTarget.addEventListener()
documentação (MDN)EventTarget.removeEventListener()
documentação (MDN)fonte
Embora
onclick
funcione em todos os navegadores,addEventListener
não funciona em versões mais antigas do Internet Explorer, que usa em seuattachEvent
lugar.A desvantagem
onclick
é que só pode haver um manipulador de eventos, enquanto os outros dois acionarão todos os retornos de chamada registrados.fonte
Até onde eu sei, o evento "load" do DOM ainda funciona apenas muito limitado. Isso significa que ele só vai disparar para o
window object
,images
e<script>
elementos por exemplo. O mesmo vale para aonload
atribuição direta . Não há diferença técnica entre os dois. Provavelmente.onload =
tem uma melhor disponibilidade entre navegadores.No entanto, você não pode atribuir um
load event
a um<div>
ou<span>
elemento ou outros enfeites.fonte
Resumo:
addEventListener
pode adicionar vários eventos, enquanto que comonclick
isso não pode ser feito.onclick
pode ser adicionado como umHTML
atributo, enquanto umaddEventListener
só pode ser adicionado dentro de<script>
elementos.addEventListener
pode aceitar um terceiro argumento que pode interromper a propagação do evento.Ambos podem ser usados para manipular eventos. No entanto,
addEventListener
deve ser a escolha preferida, pois pode fazer tudoonclick
e muito mais. Não use inlineonclick
como atributos HTML, pois isso mistura o javascript e o HTML, o que é uma prática ruim. Isso torna o código menos sustentável.fonte
onclick
handlrs em linha com medo de rir da sala - mas geralmente os eventos são vinculados de maneiras muito piores e menos fáceis nos últimos anos. Classes comojs-link
,js-form-validation
ou atributos de dados comdata-jspackage="init"
, não são de forma alguma melhores ... E com quantos anos você realmente usa a bolha de eventos? Pessoalmente, eu adoraria poder escrever um manipulador sem verificar se o alvo é realmente compatível com o meu elemento - ou ter que interromper a propagação em vários lugares devido a erros aleatórios.Um detalhe ainda não foi observado: os navegadores de desktop modernos consideram que diferentes pressionamentos de botão são "cliques" para
AddEventListener('click'
eonclick
por padrão.onclick
eAddEventListener
clique em disparar no clique esquerdo e do meio.onclick
acionado apenas no clique esquerdo, mas oAddEventListener
clique é acionado nos cliques esquerdo, central e direito.Além disso, o comportamento do clique do meio é muito inconsistente entre os navegadores quando há cursores de rolagem:
Também é importante notar que os eventos "clique" para qualquer elemento HTML selecionável pelo teclado, como
input
também são acionados no espaço ou entram quando o elemento é selecionado.fonte
Javascript tende a misturar tudo em objetos e isso pode torná-lo confuso. Tudo em um é a maneira JavaScript.
Essencialmente, onclick é um atributo HTML. Por outro lado, addEventListener é um método no objeto DOM que representa um elemento HTML.
Nos objetos JavaScript, um método é meramente uma propriedade que tem uma função como valor e que funciona contra o objeto ao qual está anexado (usando isso por exemplo).
No JavaScript, o elemento HTML representado pelo DOM terá seus atributos mapeados para suas propriedades.
É aqui que as pessoas ficam confusas porque o JavaScript mescla tudo em um único contêiner ou espaço para nome sem nenhuma camada de indireção.
Em um layout OO normal (que mescla pelo menos o espaço para nome das propriedades / métodos), você pode ter algo como:
Existem variações como ele poderia usar um getter / setter para onload ou HashMap para atributos, mas, no final das contas, seria assim. O JavaScript eliminou essa camada de indireção na expectativa de saber o que é o que há entre outras coisas. Ele mesclou domElement e atributos.
Para impedir a compatibilidade, como prática recomendada, use addEventListener. Como outras respostas falam sobre as diferenças a esse respeito, e não sobre as diferenças programáticas fundamentais, vou renunciar a isso. Essencialmente, em um mundo ideal, você realmente deve usar apenas * do HTML, mas em um mundo ainda mais ideal, você não deve fazer nada parecido com o HTML.
Por que é dominante hoje? É mais rápido de escrever, mais fácil de aprender e tende a funcionar.
O ponto principal da carga no HTML é conceder acesso ao método ou funcionalidade addEventListener em primeiro lugar. Ao usá-lo em JS, você está passando por HTML quando pode aplicá-lo diretamente.
Hipoteticamente, você pode criar seus próprios atributos:
O que JS faz é um pouco diferente disso.
Você pode equiparar a algo como (para cada elemento criado):
Os detalhes reais da implementação provavelmente diferem com uma variedade de variações sutis, tornando os dois ligeiramente diferentes em alguns casos, mas essa é a essência.
É sem dúvida um hack de compatibilidade que você pode fixar uma função em um atributo on, pois, por padrão, os atributos são todos strings.
fonte
De acordo com a MDN , a diferença é a seguinte:
addEventListener:
onclick:
Há também uma diferença de sintaxe em uso, como você vê nos códigos abaixo:
addEventListener:
onclick:
fonte
Se você não estiver muito preocupado com o suporte ao navegador, existe uma maneira de religar a referência 'this' na função chamada pelo evento. Normalmente, ele apontará para o elemento que gerou o evento quando a função é executada, o que nem sempre é o que você deseja. A parte complicada é ao mesmo tempo remover o mesmo ouvinte de evento, conforme mostrado neste exemplo: http://jsfiddle.net/roenbaeck/vBYu3/
O código acima funciona bem no Chrome e, provavelmente, há alguma restrição em tornar o "bind" compatível com outros navegadores.
fonte
O uso de manipuladores embutidos é incompatível com a Política de Segurança de Conteúdo, portanto, a
addEventListener
abordagem é mais segura desse ponto de vista. É claro que você pode habilitar os manipuladores em linhaunsafe-inline
, mas, como o nome sugere, não é seguro, pois traz de volta toda a horda de explorações de JavaScript que o CSP impede.fonte
Também deve ser possível estender o ouvinte através da criação de protótipos (se tivermos uma referência a ele e não for uma função anônima) - ou fazer o 'onclick' chamar uma chamada para uma biblioteca de funções (uma função chamando outras funções)
gostar
isso significa que nunca precisamos chocar a chamada onclick, basta alterar a função myFunctionList () para fazer o que quisermos, mas isso nos deixa sem controle das fases de captura / captura, portanto, isso deve ser evitado nos navegadores mais recentes.
caso alguém encontre esse tópico no futuro ...
fonte
Aparentemente, eles fazem o mesmo: ouvem o evento click e executam uma função de retorno de chamada. No entanto, eles não são equivalentes. Se você precisar escolher entre os dois, isso poderá ajudá-lo a descobrir qual é o melhor para você.
A principal diferença é que o onclick é apenas uma propriedade e, como todas as propriedades do objeto, se você escrever mais de uma vez, ele será substituído . Com addEventListener () , podemos simplesmente ligar um manipulador de eventos ao elemento, e podemos chamá-lo sempre que precisarmos, sem nos preocuparmos com propriedades sobrescritas. Exemplo é mostrado aqui,
Tente: https://jsfiddle.net/fjets5z4/5/
Em primeiro lugar, fiquei tentado a continuar usando o onclick, porque é mais curto e parece mais simples ... e na verdade é. Mas não recomendo mais usá-lo. É como usar o JavaScript embutido. Atualmente, o uso de algo como - que é o JavaScript embutido - é altamente desencorajado (o CSS embutido também é desencorajado, mas esse é outro tópico).
No entanto, a função addEventListener (), apesar de padrão, simplesmente não funciona em navegadores antigos (Internet Explorer abaixo da versão 9), e essa é outra grande diferença. Se você precisar oferecer suporte a esses navegadores antigos, siga o caminho do onclick. Mas você também pode usar o jQuery (ou uma de suas alternativas): basicamente simplifica o seu trabalho e reduz as diferenças entre os navegadores, portanto, você pode economizar muito tempo.
fonte
addEventListener
permite definir vários manipuladores, mas não é suportado no IE8 ou inferior.O IE tem
attachEvent
, mas não é exatamente o mesmo.fonte
O contexto referenciado pela
'this'
palavra-chave no JavasSript é diferente.veja o seguinte código:
O que ele faz é realmente simples. quando você clica no botão, o botão será desativado automaticamente.
Primeiro, quando você tenta conectar os eventos dessa maneira, o
button.onclick = function(),
evento onclick será acionado clicando no botão; no entanto, o botão não será desativado porque não há uma ligação explícita entre o manipulador de eventos button.onclick e onclick. Se você depurar ver o'this'
objeto, poderá ver que ele se refere ao'window'
objeto.Em segundo lugar, se você comentar
btnSubmit.onclick = disable();
e descomentar,//btnSubmit.addEventListener('click', disable, false);
poderá ver que o botão está desativado, pois dessa maneira há uma ligação explícita entre o evento button.onclick e o manipulador de eventos onclick. Se você depurar na função de desativação, poderá ver que'this'
se refere aobutton control
e não aowindow
.Isso é algo que eu não gosto no JavaScript, que é inconsistência. Btw, se você estiver usando jQuery (
$('#btnSubmit').on('click', disable);
), ele usa ligação explícita.fonte
btnSubmit.onclick = disable;
(atribuir função, não chamá-lo). Em ambos os casosthis
, consultará o elemento button.onclick é basicamente um addEventListener que executa especificamente uma função quando o elemento é clicado. Portanto, útil quando você tem um botão que executa operações simples, como um botão da calculadora. O addEventlistener pode ser usado para várias coisas, como executar uma operação quando o DOM ou todo o conteúdo é carregado, semelhante a window.onload, mas com mais controle.
Observe que você pode realmente usar mais de um evento com embutido ou, pelo menos, usando onclick, separando cada função com um ponto-e-vírgula, como este ....
Eu não escreveria uma função com inline, pois você pode ter problemas mais tarde e isso seria uma bagunça. Basta usá-lo para chamar funções já executadas no seu arquivo de script.
Qual você usa, suponho que depende do que você deseja. addEventListener para operações complexas e clique para simplificar. Eu já vi alguns projetos não anexarem um específico a elementos e, em vez disso, implementaria um listener de eventos mais global que determinaria se um toque estava em um botão e executaria determinadas tarefas, dependendo do que foi pressionado. Imo que poderia levar a problemas que eu pensaria e, embora pequeno, provavelmente, um desperdício de recursos, se o eventlistener tivesse que lidar com cada clique
fonte