addEventListener vs onclick

Viewed 729887

What's the difference between addEventListener and onclick?

var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);

The code above resides together in a separate .js file, and they both work perfectly.

21 Answers

Summary:

  1. addEventListener can add multiple events, whereas with onclick this cannot be done.
  2. onclick can be added as an HTML attribute, whereas an addEventListener can only be added within <script> elements.
  3. addEventListener can take a third argument which can stop the event propagation.

Both can be used to handle events. However, addEventListener should be the preferred choice since it can do everything onclick does and more. Don't use inline onclick as HTML attributes as this mixes up the javascript and the HTML which is a bad practice. It makes the code less maintainable.

An element can have only one event handler attached per event type, but can have multiple event listeners.


So, how does it look in action?

Only the last event handler assigned gets run:

const button = document.querySelector(".btn")
button.onclick = () => {
  console.log("Hello World");
};
button.onclick = () => {
  console.log("How are you?");
};
button.click() // "How are you?" 

All event listeners will be triggered:

const button = document.querySelector(".btn")
button.addEventListener("click", event => {
  console.log("Hello World");
})
button.addEventListener("click", event => {
  console.log("How are you?");
})
button.click() 
// "Hello World"
// "How are you?"

IE Note: attachEvent is no longer supported. Starting with IE 11, use addEventListener: docs.

element.onclick = function() { /* do stuff */ }

element.addEventListener('click', function(){ /* do stuff */ },false);

They apparently do the same thing: listen for the click event and execute a callback function. Nevertheless, they’re not equivalent. If you ever need to choose between the two, this could help you to figure out which one is the best for you.

The main difference is that onclick is just a property, and like all object properties, if you write on more than once, it will be overwritten. With addEventListener() instead, we can simply bind an event handler to the element, and we can call it each time we need it without being worried of any overwritten properties. Example is shown here,

Try it: https://jsfiddle.net/fjets5z4/5/

In first place I was tempted to keep using onclick, because it’s shorter and looks simpler… and in fact it is. But I don’t recommend using it anymore. It’s just like using inline JavaScript. Using something like – that’s inline JavaScript – is highly discouraged nowadays (inline CSS is discouraged too, but that’s another topic).

However, the addEventListener() function, despite it’s the standard, just doesn’t work in old browsers (Internet Explorer below version 9), and this is another big difference. If you need to support these ancient browsers, you should follow the onclick way. But you could also use jQuery (or one of its alternatives): it basically simplifies your work and reduces the differences between browsers, therefore can save you a lot of time.

var clickEvent = document.getElementByID("onclick-eg");
var EventListener = document.getElementByID("addEventListener-eg");

clickEvent.onclick = function(){
    window.alert("1 is not called")
}
clickEvent.onclick = function(){
    window.alert("1 is not called, 2 is called")
}

EventListener.addEventListener("click",function(){
    window.alert("1 is called")
})
EventListener.addEventListener("click",function(){
    window.alert("2 is also called")
})

You should also consider EventDelegation for that! For that reason I prefer the addEventListener and foremost using it carefully and consciously!

FACTS:

  1. EventListeners are heavy .... (memory allocation at the client side)
  2. The Events propagate IN and then OUT again in relation to the DOM tree. Also known as trickling-in and bubbling-out , give it a read in case you don't know.

So imagine an easy example: a simple button INSIDE a div INSIDE body ... if you click on the button, an Event will ANYWAY trickle in to BUTTON and then OUT again, like this:

window-document-div-button-div-document-window

In the browser background (lets say the software periphery of the JS engine) the browser can ONLY possibly react to a click, if it checks for each click done where it was targeted.

And to make sure that each possible event listener on the way is triggered, it kinda has to send the "click event signal" all the way from document level down into the element ... and back out again. This behavior can then made use of by attaching EventListeners using e.g.:

document.getElementById("exampleID").addEventListener("click",(event) => {doThis}, true/false);

Just note for reference that the true/false as the last argument of the addEventListener method controls the behavior in terms of when is the event recognized - when trickling in or when bubbling out.

TRUE means, the event is recognized while trickling-in FALSE means, the event is recognized on its way bubbling out

Implementing the following 2 helpful concepts also turns out much more intuitive using the above stated approach to handle:

  1. You can also use event.stopPropagation() within the function (example ref. "doThis") to prevents further propagation of the current event in the capturing and bubbling phases. It does not, however, prevent any default behaviors from occurring; for instance, clicks on links are still processed.
  2. If you want to stop those behaviors, you could use event.preventDefault() within the function (example ref. "doThis"). With that you could for example tell the Browser that if the event does not get explicitly handled, its default action should not be taken as it normally would be.

Also just note here for reference again: the last argument of the addEventListener method (true/false) also controls at which phase (trickling-in TRUE or bubbling out FALSE) the eventual effect of ".stopPropagation()" kicks in. So ... in case you apply an EventListener with flag TRUE to an element, and combine that with the .stopPropagation() method, the event would not even get through to potential inner children of the element

To wrap it up: If you use the onClick variant in HTML ... there are 2 downsides for me:

  1. With addEventListener, you can attach multiple onClick-events to the same, respectively one single element, but thats not possible using onClick (at least thats what I strongly believe up to now, correct me if I am wrong).
  2. Also the following aspect is truly remarkable here ... especially the code maintenance part (didn't elaborate on this so far):

In regards to event delegation, it really boils down to this. If some other JavaScript code needs to respond to a click event, using addEventListener ensures you both can respond to it. If you both try using onclick, then one stomps on the other. You both can't respond if you want an onclick on the same element. Furthermore, you want to keep your behavior as separate as you can from the HTML in case you need to change it later. It would suck to have 50 HTML files to update instead of one JavaScript file. (credit to Greg Burghardt, addEventListener vs onclick with regards to event delegation )

  • This is also known by the term "Unobtrusive JavaScript" ... give it a read!

I guess Chris Baker pretty much summed it up in an excellent answer but I would like to add to that with addEventListener() you can also use options parameter which gives you more control over your events. For example - If you just want to run your event once then you can use { once: true } as an option parameter when adding your event to only call it once.

    function greet() {
    console.log("Hello");
    }   
    document.querySelector("button").addEventListener('click', greet, { once: true })

The above function will only print "Hello" once. Also, if you want to cleanup your events then there is also the option to removeEventListener(). Although there are advantages of using addEventListener() but you should still be careful if your targeting audience is using Internet Explorer then this method might not work in all situation. You can also read about addEventListener on MDN, they gave quite a good explanation on how to use them.

onclick is basically an addEventListener that specifically performs a function when the element is clicked. So, useful when you have a button that does simple operations, like a calculator button. addEventlistener can be used for a multitude of things like performing an operation when DOM or all content is loaded, akin to window.onload but with more control.

Note, You can actually use more than one event with inline, or at least by using onclick by seperating each function with a semi-colon, like this....

I wouldn't write a function with inline, as you could potentially have problems later and it would be messy imo. Just use it to call functions already done in your script file.

Which one you use I suppose would depend on what you want. addEventListener for complex operations and onclick for simple. I've seen some projects not attach a specific one to elements and would instead implement a more global eventlistener that would determine if a tap was on a button and perform certain tasks depending on what was pressed. Imo that could potentially lead to problems I'd think, and albeit small, probably, a resource waste if that eventlistener had to handle each and every click

in my Visual Studio Code, addEventListener has Real Intellisense on event

enter image description here

but onclick does not, only fake ones

enter image description here

let element = document.queryselector('id or classname'); 
element.addeventlistiner('click',()=>{
  do work
})

<button onclick="click()">click</click>`
function click(){
  do work
};
Related