3

In my answer to the following SO question: What does event binding mean?, I made a passing remark that the use of inline-JavaScript/Early-Binding to bind JavaScript Events was 'often misguided'

For example:

<input id="MyButton" type="button" value="clickme" onlick="Somefunction()" />

I was arguing for the 'late-binding' approach where there is no JavaScript referenced in the markup, which I understand to be established best-practice. However, the commenters asserted that there were occasions that necessitated its use, and I wondered what these might be.

Without engaging in a discussion on the relative merits of either, can anyone think of any circumstances that dictate that you use the (e.g.) onclick attribute over a late-binding approach.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
James Wiseman
  • 29,946
  • 17
  • 95
  • 158
  • Google uses them, and so do people fiddling around. I use them when I'm making bookmarklets – qwertymk Jun 13 '11 at 13:07
  • @qwertymk: Care to expand on the bookmarklets example in an answer? I have a funny feeling it'll attract an up-vote ;-) – James Wiseman Jun 13 '11 at 13:20
  • When you control the HTML there is _no_ valid use case for inline binding. – Raynos Jun 13 '11 at 13:50
  • Raynos - I think you have that backwards. Why depend on client-side scripting to add listeners that can be added at the server more efficiently (particularly using cached or static pages), **especially** when you control the HTML? Also avoids onload/DOMReady issues with dynamic addition - listeners are available as soon as the element is. – RobG Jun 14 '11 at 06:48

3 Answers3

2

commenters asserted that there were occasions that necessitated its use

I suppose I'm one of those commentors. What I actually said was that inline listeners "are a reasonable option in certain circumstances". I don't think there are any cases where it is "necessitated" (which I understand in this context to mean required).

Adding inline listeners is simply applying the same logic on the server to add listeners as would be applied on the client and has advantages in that:

  1. Markup can be created and cached or used as static pages, listeners aren't added by every client over and over again when pages are downloaded
  2. Issues related to delay between the element being available and the listener being added by DOMReady or onload functions or "bottom scripts" are completely removed
  3. The vagaries of various "cross browser" DOMReady functions with onload fallback are removed - there is no opportunity for such functions to fail to add listeners if they aren't used

Of course this doesn't mean that all listeners should be added inline and that dynamic addition of listeners is rubbish, I'm just point out that it is a viable method that solves certain issues and is a perfectly reasonable solution in many cases.

If you believe "early binding" of listeners is good, then make it as early as possible - put them inline. :-)

PS. I also think I said I didn't like the use of "binding" in this context as listeners aren't bound to elements in any real sense. They are simply functions that are called when an element receives a related event. The only type of binding is that the listener's this keyword may be set to reference the related element (which is consistent in all browsers for inline listeners but not necessarily for those added later).

RobG
  • 142,382
  • 31
  • 172
  • 209
  • "1. Markup can be created and cached or used as static pages, listeners aren't added by every client over and over again when pages are downloaded" JavaScript files that attach listeners are cached. Listeners are added by every client over and over again. This happens when the browser parses the DOM and attaches the listeners for you. – Raynos Jun 14 '11 at 07:18
  • "2. Issues related to delay between the element being available and the listener being added by DOMReady or onload functions or "bottom scripts" are completely removed" The delay should be small. Clients should not be encouraged to interact with the page before it has finished loading as this requires you to code significantly more defensively and guard against "partial loaded state bugs". If the delay is noticeable then your doing your loading wrong i.e. not enough caching / lazy loading. – Raynos Jun 14 '11 at 07:19
  • "3 The vagaries of various "cross browser" DOMReady functions with onload fallback are removed - there is no opportunity for such functions to fail to add listeners if they aren't used" If a particular developer does not use a DOMReady utility library then they are shooting themself in the foot for no reason. [domReady](https://github.com/ded/domready) is just 0.5kb. There is no reason to not use it. – Raynos Jun 14 '11 at 07:21
  • +1 for showing solid reasoning for using inline events though! – Raynos Jun 14 '11 at 07:22
  • +1 From me as well. This sort of discussion is exactly why I like SO. – James Wiseman Jun 14 '11 at 07:36
  • James - SO actively discourages discussion by its [policy](http://stackoverflow.com/faq) and posting structure. That's why this "discussion" has been continued in a separate question. Most discussion topics are closed very quickly. – RobG Jun 15 '11 at 00:00
  • Raynos - regarding #2, you have no control whatever over how quickly pages load or are displayed other than size. Network latency between server and client is, in most cases, completley unknown and can vary hugely between consecutive requests from the same client, particularly if a mobile network or device is involved. Users should not have to wait until the entire page is downloaded before they can work with it. – RobG Jun 15 '11 at 00:04
2

Reasons why onclick attributes are bad :

onclick="foo()"

  • Your passing in a string of code that get's evalled at runtime when the element is clicked. This is inefficient and uses the horrors of eval
  • Your forced to store the function foo in global scope thus polluting global scope with all your event handling logic.
Raynos
  • 166,823
  • 56
  • 351
  • 396
  • The code is not "evalled at runtime", it is parsed as the page loads and is called by a handler (just like dynamically added listeners), in most cases it is a single function call. The "horrors of eval" are irrelevant (and much over stated). Talk of "polluting the global scope" with additional properties is scare mongering, the only issue is name collisons and they are easily avoided. – RobG Jun 15 '11 at 01:03
1

I think many developers will do this either due to ignorance or lack of knowledge (which is, of course, common) and the remaining developers will do it because it's simply more convenient to use HTML-JS attributes than late binding, if you know that certain objects and functions are always loaded on every page and they will simply 'be there'.

I think this is especially true when said HTML comes from an AJAX callback. Take an example where an AJAX request comes back with an HTML response and that HTML is inserted into the page. Now the naive developer would think along these lines:

  • I have no idea what elements are inside that response HTML so I don't know what late bindings I need to add.
  • Perhaps I need to add them all just in case! Or write some parsing script that detects elements and binds to the ones I find?
  • But what if I need to bind to something that doesn't already exist? Time to write some long inline JavaScript!

All of this can be eliminated by using a kind of omnipresent binding that applies to all current and future elements on the page. In jQuery, the equivalent is live(). Instead of writing:

$('.foo').click(function(){...});

You could write:

$('.foo').live('click', function(){...});

Now, all elements with class name 'foo' will execute the function when clicked, including elements that don't currently exist. Very useful for dynamic AJAX interfaces.

You may know that already, but I'm just pointing out that anything JS attributes can do, pure JS can do better, and I'd consider that best practise.

BoffinBrain
  • 6,337
  • 6
  • 33
  • 59
  • +1 Suberb answer. Yes, I did know, but there's nothing better than an assertion that your reality is as you perceieve :-) – James Wiseman Jun 13 '11 at 13:49
  • 1
    `.live` is the devil. Use `.delegate` – Raynos Jun 13 '11 at 13:50
  • @Raynos Nice find. I knew `live()` had a few issues but didn't know I could do the same thing at a lower level in the DOM. Good for performance, I guess. – BoffinBrain Jun 13 '11 at 14:28
  • 1
    For the rest [See @NickCraver's excellent explanation of why `.live` is bad](http://stackoverflow.com/questions/4204316/jquery-live-vs-delegate/4204349#4204349) – Raynos Jun 13 '11 at 14:35