This article has been machine-translated from Chinese. The translation may contain inaccuracies or awkward phrasing. If in doubt, please refer to the original Chinese version.
Today the interviewer asked this question: What are the differences between onclick and addEventListener?
Great question — it stumped me. I wasn’t satisfied with my answer, so afterward I looked it up in “JavaScript: The Definitive Guide” (the “Red Book”) Chapter 17 on Events and MDN. Here’s what I found.
Let me start with the answer:
Differences
addEventListener() is the method specified in the W3C DOM specification for registering event listeners. Its advantages include:
- Allows registering multiple listeners for a single event
- Particularly useful when working with AJAX libraries, JavaScript modules, or other code that requires third-party libraries/plugins
- Provides a more fine-grained way to control the triggering phase of
listener(you can choose capturing or bubbling) - It works on any DOM element, not just HTML elements.
- Events registered with it can be removed via
removeEventListener- This also means anonymous event functions cannot be removed
- The value of
thisis a reference to the element that triggered the eventconsole.log(e.currentTarget === this) // true
On the other hand, onclick is the old way of registering listeners
- This method will replace all existing onclick events on the element, and other on-events work similarly.
- Cannot provide fine-grained control over bubbling, etc.
- Removal can be done by directly replacing the onclick event with null
Compatibility
addEventListener was introduced in the DOM 2 Events specification
- Before IE 9,
attachEventhad to be used instead ofaddEventListener attachEventhas a drawback: the value ofthisbecomes a reference to thewindowobject rather than the element that triggered the event
Meanwhile, onclick is basic content from the DOM 0 specification
- Almost all browsers support it, and it doesn’t require special cross-browser compatibility code
- Therefore, this method is often used to dynamically register event handlers, unless the special features that only
addEventListener()can provide are needed
addEventListener
EventTarget.addEventListener() registers the specified listener on the
EventTarget. When the object triggers the specified event, the specified callback function is executed. The event target can be anElementin the document, aDocument, aWindow, or any other object that supports events (such asXMLHttpRequest).
addEventListener()works by adding a function or object that implementsEventListenerto the list of event listeners for the specified event type on theEventTargeton which it is called.
addEventListener takes three parameters: type, listener, and useCapture. The first parameter is the event type (e.g., click, mousemove), the second is the callback function for the event, and the third is an optional parameter object specifying properties about the listener. Important to note:
In older versions of the DOM specification, the third parameter of
addEventListener()was a boolean indicating whether to call the event handler during the capture phase. Over time, it became clear that more options were needed. Rather than adding more parameters to the method (which would make passing optional values extremely complicated), the third parameter was changed to an object containing various properties whose values configure the event listener removal process.
Since older browsers (and some relatively recent ones) still assume the third parameter is a boolean, you need to write code to effectively handle this situation. You can do feature detection for each options value you’re interested in.
In other words, addEventListener requires additional code for compatibility with older browsers, while onclick does not. This needs careful consideration in scenarios where compatibility matters.
this in Events
In addEventListener, the value of this is typically a reference to the element that triggered the event — console.log(e.currentTarget === this) // true
However, arrow functions are different. Arrow functions don’t have their own this — they inherit this from the upper level of their scope chain.
onclick
The
onclickproperty of theGlobalEventHandlersis the event handler for theclickevent of the current element.
When a user clicks an element, a
clickevent is triggered. The order of theclickevent in the entire click process comes after themousedownandmouseupevents.
Note: When using the
clickevent to trigger an action, also consider adding this action to thekeydownevent to allow users who don’t use a mouse or touchscreen to perform the same action. The MDN documentation doesn’t go into much detail, but the Red Book has several important points about onclick.
Extended Scope Chain
<script>
function showMessage() {
console.log("Hello world!");
}
</script>
<input type="button" value="Click Me" onclick="showMessage()"/>
An event handler specified via onclick in this way creates a function that wraps the attribute’s value. (This approach is not recommended, reasons explained at the end.)
This function has a special local variable event, which holds the event object:
<!-- outputs "click" -->
<input type="button" value="Click Me" onclick="console.log(event.type)" />
With this object, developers don’t need to define additional variables or extract them from the wrapper function’s parameter list. In this function, the this value is equivalent to the event’s target element, as shown below:
<!-- outputs "Click Me" -->
<input type="button" value="Click Me" onclick="console.log(this.value)" />
A particularly interesting aspect of this dynamically created wrapper function is that its scope chain is extended. In this function, document and the element’s own members can be accessed as local variables. This is achieved using with:
function() {
with(document) {
with(this) {
// property value
}
}
}
This is also why events defined with onclick can call events on document without the document prefix — there’s actually an additional layer of wrapping in front.
One problem with using HTML to specify onclick event handlers is that it creates tight coupling between HTML and JavaScript. If you need to modify the event handler, you must make changes in both HTML and JavaScript. This is the main reason why HTML event handlers are discouraged, and JavaScript-specified event handlers are recommended instead.
So in JavaScript, when you truly need to use onclick, use the following approach:
let btn = document.getElementById('myBtn');
btn.onclick = function (e) {
console.log(e.type); // "click"
};
喜欢的话,留下你的评论吧~