4

HTML Event Attributes:

<button onclick="displayDate()">Try it</button> 

Assign Events Using the HTML DOM:

<script> document.getElementById("myBtn").onclick = function(){ displayDate() }; </script> 

What is the difference between these two ? Any advantages in using (Assign Events Using the HTML DOM) ?

Thanks

1
  • 1
    I guess the main point is: keep things separate. Don't put javascript or CSS in the middle of HTML markup. If there is one reason you look for, let that be it. For the rest, both work just fine. Commented Jan 12, 2015 at 15:18

4 Answers 4

8

There are very big differences.

Event handlers that are set up via HTML event attributes were the first way we did event handling - - before there was a DOM. This way of setting up events became known as DOM Level 0 (as in, the de facto standard before there was a standard). When this was the way to do it (circa 1995), it was fine, because we had no other choice. But, the way the attribute value was turned into event handling code was handled like this:

The HTML element has an event attribute declared on it and that attribute has a value that is the JavaScript code that should be executed when the event occurs:

<input type="button" onclick="alert('You clicked me!')" value="Click me">

Notice that the value of onclick isn't a function reference, just loose code to run.

This is actually implemented by the browser by creating a function in the Global scope that acts as a wrapper for the supplied code. We can see that here:

// Output the value of the onclick property. // Note the value supplied in the HTML // is wrapped in a function that we didn't create alert(document.querySelector("input").onclick);
<input type="button" onclick="alert('You clicked me!')" value="Click me">

Because of this automatic wrapping of the attribute value in a Global wrapper function, non-intuitive things often happened like this:

function foo(){ // This function is invoked by clicking the HTML input element // so, we may reasonably expect that "this" would reference that // element. But, as you'll see, it doesn't. alert("You clicked the " + this.nodeName + " element."); }
<input type="button" onclick="foo()" value="Click me">

The above reports undefined because in actuality, this in that context is referring to the Global window object, which doesn't have a nodeName property. But, if you didn't know about the Global wrapper (and why would you), this would be very confusing because this used by a DOM event handler almost always references the DOM element that caused the event to fire.

When the DOM Level 1 Event Handling specification came out (1998), a new way of configuring events came about as well. We now had objects that represented the HTML elements and each object had properties that mapped to the attributes of the element. For this reason many people (up to this very day) still believe that working with attributes or object properties is largely the same thing. But, there are important differences (which I've written about in this other answer of mine: see second half of answer) as attributes are used to set values, which can affect state, but properties are used to override attributes and set state.

So, with DOM event handling, we'd do the following, which you will see, sets up the event callback, not as loose code to be executed, but by storing a reference to a function to be invoked when the event occurs. Because we supply the function, it has the scope of the DOM object we store it with and we no longer need to wrap loose commands with a Global. This causes this binding to work as expected:

// Just a reference to a function is used with event // properties. Not "loose" code. And, because the function // is actually being stored with the DOM element, this binding // works as expected. document.querySelector("input").onclick = foo; function foo(){ // This function is invoked by clicking the HTML input element // so, we may reasonably expect that "this" would reference that // element. But, as you'll see, it doesn't. alert("You clicked the " + this.nodeName + " element."); }
<input type="button" value="Click me">

The additional benefit of DOM Event handling was that we kept the JavaScript stuff separate from the HTML stuff (ie. separation of concerns). This was a benefit, but not the driving force for the change.

Now, having explained the differences between those two mechanisms for registering events, the story isn't complete. There is still an problem with DOM event properties in that if you wanted to set up multiple event handlers, you didn't have a clean way to do that since you can only store one function reference in a given property. So, with modern event handling, we use .addEventListener(), which allows us to register as many event callbacks with an event that we want and we get the added benefit of knowing that the callbacks we register will be invoked in the order that we registered them.

// Register an event listener: document.querySelector("input").addEventListener("click", foo1); // Register more event listeners: document.querySelector("input").addEventListener("click", foo3); document.querySelector("input").addEventListener("click", foo2); function foo1(){ console.log("Hello from foo1"); } function foo2(){ console.log("Hello from foo2"); } function foo3(){ console.log("Hello from foo3"); }
<input type="button" value="Click me">

Sign up to request clarification or add additional context in comments.

5 Comments

I'm relearning Vanilla Javascript and I get confused when it is said, only one event can be attached when using event attribute, so you would need to use an eventlistener. When I do something like, <input onkeyup="DisplayResults(); sendAlert()" onsearch="ClearResults()"> each event is fired appropriately, and multiple functions are even called when two are added to one event attribute. Can you help me clear up this confusion? Thank you.
@eaglei22 What I wrote was There is still an problem with DOM event properties in that if you wanted to set up multiple event handlers, you didn't have a clean way to do that since you can only store one function reference in a given property. This does not refer to inline HTML event attributes, this refers to using "event properties" in JavaScript. For example, if you write element.click = foo; and then write element.click = bar' the second statement overwrites the value of the click property set in the first statement so if the element gets clicked only bar would execute.
@eaglei22 When you use inline HTML event attributes, the same is true: <input onclick="foo" onclick="bar"> would only execute bar when the element is clicked. Yes, you could write <input onclick="foo(); bar()">; but then you would always be executing foo and bar when the element gets clicked, so you've lost the ability to be granular when setting up your event handlers.
@eaglei22 But, if you use the modern approach, you can do this: element.addEventListener("click", foo); element.addEventListener("click", bar); and know that when the element gets clicked foo will run and then bar. You can even register and deregister event handlers dynamically with this approach. Additionally, with this approach, a reference to the event itself is automatically passed into the event handler. That doesn't happen with inline HTML event attribute set ups.
Ahh, that clears things up much better for me now, Thank you! And thank you for your quick response and detailed responses. It was the properties that I was getting hung up on and had forgotten about. It seemed many of the Google search results I came across wasn't clear on this or would demonstrate an element with one inline html event attribute, and an event listener, then mentioned the event listener would allow for multiple events; sometimes even saying you could only add one event using inline.. Adding even more confusion! Makes much more sense however, with your examples. Thanks!
1

The difference (or, rather, connection) is described in clause 6.1.5 Events of the HTML5 specification. The basic difference is that an event attribute like onclick contains JavaScript code (typically, a function invocation) that is executed as such, whereas the click property of an element node is a reference to a function definition. If you use, say, onclick="displayDate()" in HTML source and then inspect the DOM in a browser’s developer tools, you’ll see that the connection is more complicated in principle.

The practical difference is large a matter of opinion and coding style. Using the onclick attribute makes it immediately obvious to anyone reading the HTML source code that an event handler is present. This may also be disadvantage, when reading the HTML code primarily as structured data. But there is a definite technical advantage when several elements need to have the same event handler, e.g. when you want a click on any link trigger some handler (before or instead of normal following link operation). Using JavaScript, you can have a loop that assigns the same function to all links, as opposite to copying the same onclick attribute in HTML markup.

Comments

0

The advantage is you don't mess js code with html, it permits you to separate programming layers. This renders your code cleaner and less prone to bugs. A practice that complies with web accessibility rules and good programming foundations.

1 Comment

No. There are very big differences in how the event callback is established and potential side-effects. See my detailed answer below.
-1

There is no difference. OnClick it's the same event.

If you want to call different methods , with javascript you can manipulate what to do when OnClick it's raised.

1 Comment

While the event is the same, these two techniques have very different ways of configuring the callback. Scope for the two is different.