13

Look at this code:

<button onclick="handler()">ClickMe</button>
        <script>
            function handler() {
            alert("clicked");
        }
     </script>

Why onclick event should be assigned to handler with () onclick="handler()"? In this case alert is called. But according to the logic described as answer to similar question https://stackoverflow.com/a/3247044/2543590 onclick assigned to result of function handler, not to function itself. I believe to assign onclick to function it should be like this

onclick="handler", 

but in this case alert is not called. Why?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Vitaliy Markitanov
  • 2,205
  • 1
  • 24
  • 23
  • 4
    JavaScript gurus would tell you not to bind inline event handlers in your markup. – user229044 Dec 10 '13 at 03:24
  • 2
    An example of when it's useful to use inline handlers is when you need to ensure that there's no latency between the element being available, and the element being fully functional. This doesn't happen often, but inline handlers solve this problem nicely. Gurus would tell you to use the right tool for the job. – Blue Skies Dec 10 '13 at 03:51
  • 3
    "Gurus" will tell you to understand the consequences of different design decisions, then chose the one that best applies to a circumstance based on some criteria for "best". – RobG Dec 10 '13 at 04:38

4 Answers4

14

Inline JS

When you do an inline onclick handler like that, you're assigning a Javascript expression to run. So you need to execute the function.

The expression could just as easily be onclick="handler();alert(2)" in which case its obvious that the function needs to be called, just like it would be if it were run from a javascript file.

Binding a function to the click event

If instead you attach the click event with javascript, you would be binding a function, so you just need to pass the function object.

var btn = document.getElementById("btn");
btn.addEventListener("click",handler);

addEventListener sets the function object to be bound to the event so that it executes when the event is triggered. Since you're specifying a function object, rather than a string expression, the parentheses are not needed. In fact if you added them the function would execute immediatelly and the return value of the function would be bound to the event.

Best Practice

In general most people would advocate you bind events in javascript by binding a function handler rather than using inline JS. Its easier to debug, doesn't tightly bind your logic to the DOM, and is more flexible for dynamic pages. It also forces you to make any functions that you're calling global.

Summary

The key is the attribute points to a string that is evaluated as a JS expression, it is not the same as binding a function object to the event.

Ben McCormick
  • 25,260
  • 12
  • 52
  • 71
  • I'm going to nitpick just a tiny bit. Having a single function call doesn't really bind logic to the DOM any more than having a class on the element for the purpose of binding a handler after the DOM is loaded. I agree that for the most common case, inline handler's aren't the best approach, but there are times when they're very useful. – Blue Skies Dec 10 '13 at 03:36
  • @BlueSkies sure it does. If you have a class, you can change the functionality without changing the DOM. If you have the inline function, you can't change the expression without changing the DOM. Thus it is more tightly bound. – Ben McCormick Dec 10 '13 at 03:38
  • If you change the DOM, could be that you'll need to change the DOM selection which selects the element(s) for the handler assignment. Neither way is perfectly pure. – Blue Skies Dec 10 '13 at 03:40
10

Because onclick="handler" isn't JavaScript. It's an attribute of your tag. Yes, if this were JavaScript, you'd be able to pass in the function itself, but it's not; you're assigning a statement to be executed on click.

The statement executed by onclick="handler" basically does this:

<script>
handler;
</script>

IE, nothing.

user229044
  • 232,980
  • 40
  • 330
  • 338
6

Anything you put inside onclick="" will be wrapped with an implicit function. That is the actual event handler that will be called on click, any function call inside it needs the parentheses.

bfavaretto
  • 71,580
  • 16
  • 111
  • 150
  • wrapped with anonymous function. `function(){ handler(); } ` That's more correct term. – yigitt Feb 18 '22 at 11:59
  • 1
    Actually, that's not what I meant. The function there is implicit, because there's no visible function syntax. Whether the actual function created around the attribute is anonymous or named, that's an implementation detail. – bfavaretto Feb 18 '22 at 12:58
  • 1
    I get it. nice. I checked it on chrome. it is wrapped with anonymous function and attached to the onclick event handler. – yigitt Feb 18 '22 at 13:47
  • @bfavaretto Could you elaborate on how it's wrapped with an implicit function? Could we write our own html attribute that that behaves in the same way as onclick. In that it calls a function with arguments without using some form of eval? – Nick Aug 24 '23 at 19:51
  • I don't think you can make it work for custom attributes without eval. The standard events word like that as dictated by the spec, see https://html.spec.whatwg.org/dev/webappapis.html#event-handler-attributes @Nick – bfavaretto Aug 24 '23 at 21:03
5

All on-attributes on elements actually set inline Javascript, not a handler. So you're actually executing code there, in this case a function call. If you leave out the parentheses, it's just invalid code.

Compare:

<button onclick="alert('click!')">Click me!</button>
Niels Keurentjes
  • 41,402
  • 9
  • 98
  • 136