6

I am developing a web application and using quite a lot of JavaScript doing tasks. I have quite some tags that are bound with Jquery click to do some jobs, so I have code like this:

html code:

 <a href="#" id="id1">some content here</a>
 <a href="#" id="id2">some content here</a>
 ....

Jquery code:

 $('#id1').click(function(){
     //do something here..
     return false;
 });

 $('#id2').click(function(){
     //do something else here..
     return false;
 });

with this approach, when the script runs, jquery must look up the selectors (id1,id2, ect).

but there is another approach which avoid looking up selectors , this is as follow:

<a href="requireJs.htm" onclick="f1();return false">some content here</a>
<a href="requireJs.htm" onclick="f2();return false">some content here</a>

and js code:

 function f1(){
     //do something here..
 });

 function f2(){
     //do something else here..
 });

which approach is better, considering performance? thanks for help.

bingjie2680
  • 7,643
  • 8
  • 45
  • 72

5 Answers5

6

Forget performance - any difference between the two will be inconsequential.

The first approach is MUCH better as it maintains a strict separation between behaviour and content.

Incidentally, the performance difference is only incurred on assigning the event-handler. In this case the inline-call does not have to "find" the dom element, however, since your jquery selector is selecting by id (which is very efficient), the "overhead" incurred by the extra step will be tiny.

BonyT
  • 10,750
  • 5
  • 31
  • 52
6

The real performance gain is by using only one event handler attached to the parent element, and catch the children element generated event with event.target, since events bubble up by default in JavaScript to the outermost parent.

Wrap your link in a div

<div id="parent">
 <a href="#" id="id1">some content here</a>
 <a href="#" id="id2">some content here</a>
</div>

Attach only one event listener to it

$('#parent').click(function(event){
    // event.target is now the element who originated the event
    $(event.target).doSomething();
});

This is a big increase in speed, expecially in older browsers such as IE, and when you start to have really many events.

View example here

Jose Faeti
  • 12,126
  • 5
  • 38
  • 52
  • 1
    so can I just wrap all content inside a
    – bingjie2680 Aug 05 '11 at 14:34
  • By default events in JS bubble up until they find an event listener. So for example I click on a deeply nested element, the event will wrap up up to the body element (maybe even html, not sure), so you could potentially attach only an event listener to the body for everything. Beware though that this bubbling up in the chain will be slower as more element the engine has to bubble up. This is the same for variables, always declare them with the var statement, otherwise the script will look up the chain for a variable already initialized with that name, and if it find it, it will use that value! – Jose Faeti Aug 05 '11 at 14:38
  • thanks for explanation, then I have to check like the envent.target==id1 and do something, am I geting that right? – bingjie2680 Aug 05 '11 at 14:41
  • There is an issue with this. Because you are binding the PARENT you can't stop propagation on the event at the child level. As demostrated with this jsfiddle...http://jsfiddle.net/xZAGr/11/ – kasdega Aug 05 '11 at 14:59
  • Of course, cause the event already propagated, but what's the point in stopping the propagation then? Why do you need that? If the problem is the default behavior you could still doing like this http://jsfiddle.net/xZAGr/12/ to prevent the default behavior. – Jose Faeti Aug 05 '11 at 15:04
3

Performance wise inline call is fast because it is triggered right away whereas if you use jquery it listens to this event and finds all the attached handlers and executes them in sequence. But using jquery you can manage to attach as many handlers you want in a systematic way.

ShankarSangoli
  • 69,612
  • 13
  • 93
  • 124
2

One possibility would be to use .delegate() where you can set context specific bindings. This should be faster than both .live() and several .click() bindings due to how delegate works. There is an excellent write up on this here, an EXCELLENT MUST READ in SO here. Good Luck!

HTML

<div id="wrapper">
   <a href="#" id="id1">some content here</a>
   <a href="#" id="id2">some content here</a> 
</div>

Jquery/Javascript

$("#wrapper").delegate("#id1", "click", function(e){
   e.preventDefault();
   //do something here..
});

Jquery Delegate API

Community
  • 1
  • 1
kasdega
  • 18,396
  • 12
  • 45
  • 89
0

According to Jose Faeti's answer, here are two questions:

The problem is, that an anchor-tag which contains other elements - such as divs, or spans - is not seen as clicked. It's child-element is tho.

<div id="foo">
    <a class="clickable" href="#a1" name="a1"><div>hello</div></a><br/>
    <div>i don't need to be listened to</div>

    <a class="clickable" href="#a2" name="a2"><div><span>there</span></div></a>
    <div>neither me, only a-tags should be concerned</div>

    <a class="clickable" href="#a3" name="a3">only i am "really" listened to</a>
    <div>more content</div>
</div>

This might be ugly, but in our existing application, that's the current state. So I reformed the according JavaScript as following:

$('#foo').click( function ( event ) {
    event.preventDefault();

    if( $(event.target).hasClass('clickable') ) {
        alert('clicked: ' + event.target.name );
    } else {
        if( $(event.target).closest('a.clickable').length )
            alert('has parent: ' + $(event.target).closest('a.clickable').attr('name') );
    }
});

My question: Is there any better solution to this? More performant? Is it ugly or would you do different?

Cheers

Boris
  • 577
  • 4
  • 15