# javascript – addEventListener vs onclick

## The Question :

766 people think this question is useful

What’s the difference between addEventListener and onclick?

var h = document.getElementById("a");
h.onclick = dothing1;



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

1037 people think this answer is useful

Both are correct, but none of them are “best” per se, and there may be a reason the developer chose to use both approaches.

Event Listeners (addEventListener and IE’s attachEvent)

Earlier versions of Internet Explorer implement javascript differently from pretty much every other browser. With versions less than 9, you use the attachEvent[doc] method, like this:

element.attachEvent('onclick', function() { /* do stuff here*/ });



In most other browsers (including IE 9 and above), you use addEventListener[doc], like this:

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



Using this approach (DOM Level 2 events), you can attach a theoretically unlimited number of events to any single element. The only practical limitation is client-side memory and other performance concerns, which are different for each browser.

The examples above represent using an anonymous function[doc]. You can also add an event listener using a function reference[doc] or a closure[doc]:

var myFunctionReference = function() { /* do stuff here*/ }

element.attachEvent('onclick', myFunctionReference);



Another important feature of addEventListener is the final parameter, which controls how the listener reacts to bubbling events[doc]. I’ve been passing false in the examples, which is standard for probably 95% of use cases. There is no equivalent argument for attachEvent, or when using inline events.

Inline events (HTML onclick=”” property and element.onclick)

In all browsers that support javascript, you can put an event listener inline, meaning right in the HTML code. You’ve probably seen this:

<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>



Most experienced developers shun this method, but it does get the job done; it is simple and direct. You may not use closures or anonymous functions here (though the handler itself is an anonymous function of sorts), and your control of scope is limited.

The other method you mention:

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



… is the equivalent of inline javascript except that you have more control of the scope (since you’re writing a script rather than HTML) and can use anonymous functions, function references, and/or closures.

The significant drawback with inline events is that unlike event listeners described above, you may only have one inline event assigned. Inline events are stored as an attribute/property of the element[doc], meaning that it can be overwritten.

Using the example <a> from the HTML above:

var element = document.getElementById('testing');
element.onclick = function () { alert('did stuff #1'); };
element.onclick = function () { alert('did stuff #2'); };



… when you clicked the element, you’d only see “Did stuff #2” – you overwrote the first assigned of the onclick property with the second value, and you overwrote the original inline HTML onclick property too. Check it out here: http://jsfiddle.net/jpgah/.

Broadly speaking, do not use inline events. There may be specific use cases for it, but if you are not 100% sure you have that use case, then you do not and should not use inline events.

Modern Javascript (Angular and the like)

Since this answer was originally posted, javascript frameworks like Angular have become far more popular. You will see code like this in an Angular template:

<button (click)="doSomething()">Do Something</button>



This looks like an inline event, but it isn’t. This type of template will be transpiled into more complex code which uses event listeners behind the scenes. Everything I’ve written about events here still applies, but you are removed from the nitty gritty by at least one layer. You should understand the nuts and bolts, but if your modern JS framework best practices involve writing this kind of code in a template, don’t feel like you’re using an inline event — you aren’t.

Which is Best?

The question is a matter of browser compatibility and necessity. Do you need to attach more than one event to an element? Will you in the future? Odds are, you will. attachEvent and addEventListener are necessary. If not, an inline event may seem like they’d do the trick, but you’re much better served preparing for a future that, though it may seem unlikely, is predictable at least. There is a chance you’ll have to move to JS-based event listeners, so you may as well just start there. Don’t use inline events.

jQuery and other javascript frameworks encapsulate the different browser implementations of DOM level 2 events in generic models so you can write cross-browser compliant code without having to worry about IE’s history as a rebel. Same code with jQuery, all cross-browser and ready to rock:

eval(v.myclick); // eval($(v).attr('myclick')); }); });  What JS does with is a bit different to that. You can equate it to something like (for every element created): element.addEventListener('click', function() { switch(typeof element.onclick) { case 'string':eval(element.onclick);break; case 'function':element.onclick();break; } });  The actual implementation details will likely differ with a range of subtle variations making the two slightly different in some cases but that’s the gist of it. It’s arguably a compatibility hack that you can pin a function to an on attribute since by default attributes are all strings. ## The Answer 10 2 people think this answer is useful According to MDN, the difference is as below: addEventListener: The EventTarget.addEventListener() method adds the specified EventListener-compatible object to the list of event listeners for the specified event type on the EventTarget on which it’s called. The event target may be an Element in a document, the Document itself, a Window, or any other object that supports events (such as XMLHttpRequest). onclick: The onclick property returns the click event handler code on the current element. When using the click event to trigger an action, also consider adding this same action to the keydown event, to allow the use of that same action by people who don’t use a mouse or a touch screen. Syntax element.onclick = functionRef; where functionRef is a function – often a name of a function declared elsewhere or a function expression. See “JavaScript Guide:Functions” for details. There is also a syntax difference in use as you see in the below codes: addEventListener: // Function to change the content of t2 function modifyText() { var t2 = document.getElementById("t2"); if (t2.firstChild.nodeValue == "three") { t2.firstChild.nodeValue = "two"; } else { t2.firstChild.nodeValue = "three"; } } // add event listener to table var el = document.getElementById("outside"); el.addEventListener("click", modifyText, false);  onclick: function initElement() { var p = document.getElementById("foo"); // NOTE: showAlert(); or showAlert(param); will NOT work here. // Must be a reference to a function name, not a function call. p.onclick = showAlert; }; function showAlert(event) { alert("onclick Event detected!"); }  ## The Answer 11 1 people think this answer is useful If you are not too worried about browser support, there is a way to rebind the ‘this’ reference in the function called by the event. It will normally point to the element that generated the event when the function is executed, which is not always what you want. The tricky part is to at the same time be able to remove the very same event listener, as shown in this example: http://jsfiddle.net/roenbaeck/vBYu3/ /* Testing that the function returned from bind is rereferenceable, such that it can be added and removed as an event listener. */ function MyImportantCalloutToYou(message, otherMessage) { // the following is necessary as calling bind again does // not return the same function, so instead we replace the // original function with the one bound to this instance this.swap = this.swap.bind(this); this.element = document.createElement('div'); this.element.addEventListener('click', this.swap, false); document.body.appendChild(this.element); } MyImportantCalloutToYou.prototype = { element: null, swap: function() { // now this function can be properly removed this.element.removeEventListener('click', this.swap, false); } }  The code above works well in Chrome, and there’s probably some shim around making “bind” compatible with other browsers. ## The Answer 12 1 people think this answer is useful Using inline handlers is incompatible with Content Security Policy so the addEventListener approach is more secure from that point of view. Of course you can enable the inline handlers with unsafe-inline but, as the name suggests, it’s not safe as it brings back the whole hordes of JavaScript exploits that CSP prevents. ## The Answer 13 1 people think this answer is useful It should also be possible to either extend the listener by prototyping it (if we have a reference to it and its not an anonymous function) -or make the onclick call a call to a function library (a function calling other functions). Like: elm.onclick = myFunctionList; function myFunctionList(){ myFunc1(); myFunc2(); }  This means we never have to change the onclick call just alter the function myFunctionList() to do whatever we want, but this leaves us without control of bubbling/catching phases so should be avoided for newer browsers. ## The Answer 14 0 people think this answer is useful addEventListener lets you set multiple handlers, but isn’t supported in IE8 or lower. IE does have attachEvent, but it’s not exactly the same. ## The Answer 15 0 people think this answer is useful The context referenced by 'this' keyword in JavasSript is different. look at the following code: <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title></title> </head> <body> <input id="btnSubmit" type="button" value="Submit" /> <script> function disable() { this.disabled = true; } var btnSubmit = document.getElementById('btnSubmit'); btnSubmit.onclick = disable(); //btnSubmit.addEventListener('click', disable, false); </script> </body> </html>  What it does is really simple. when you click the button, the button will be disabled automatically. First when you try to hook up the events in this way button.onclick = function(), onclick event will be triggered by clicking the button, however, the button will not be disabled because there’s no explicit binding between button.onclick and onclick event handler. If you debug see the 'this' object, you can see it refers to 'window' object. Secondly, if you comment btnSubmit.onclick = disable(); and uncomment //btnSubmit.addEventListener('click', disable, false); you can see that the button is disabled because with this way there’s explicit binding between button.onclick event and onclick event handler. If you debug into disable function, you can see 'this' refers to the button control rather than the window. This is something I don’t like about JavaScript which is inconsistency. Btw, if you are using jQuery($('#btnSubmit').on('click', disable);), it uses explicit binding.

0 people think this answer is useful

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 btn = document.querySelector(".btn")
button.onclick = () => {
console.log("Hello World");
};
button.onclick = () => {
console.log("How are you?");
};
button.click() // "Hello World"



All event listeners will be triggered:

const btn = document.querySelector(".btn")
console.log("Hello World");
})
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.

0 people think this answer is useful

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

but onclick does not, only fake ones