The Difference Between jQuery’s .bind(), .live(), and .delegate()

The difference between .bind(), .live(), and .delegate() is not always apparent. Having a clear understanding of all the differences, though, will help us write more concise code and prevent bugs from popping up in our interactive applications.
The jQuery team have announced in v1.7 a new method for binding events called on. This method combines the functionality of live, bind, and delegate described below, allowing you to specify the binding method based the arguments passed rather than by using different function names.
The basics
The DOM tree
First, it helps to visualize the DOM tree of an HTML document. A simple HTML page would look like this:
Event bubbling (aka event propagation)
When we click a link, it fires the click event on the link element, which triggers any functions we bound to that element’s click event.
So a click will trigger the alert.
That click event then propagates up the tree, broadcasting to the parent element and then to each ancestor element that the click event was triggered on one of the descendent elements.
In the context of manipulating the DOM, document is the root node.
Now we can more easily illustrate the difference between .bind(), .live(), and .delegate().
.bind()
This is the most straight forward binding method. jQuery scans the document for all $('a') elements and binds the alert function to each of their click events.
.live()
jQuery binds the alert function to the $(document) element, along with 'click' and 'a' as parameters. Any time an event bubbles up to the document node, it checks to see if the event was a click and if the target element of that event matches the 'a' CSS selector. If both are true, the function executes.
The live method can also be bound to a specific element (or “context”) other than document, like this:
.delegate()
jQuery scans the document for $('#container'), and binds the alert function along with the click event and 'a' CSS selector as parameters. Any time an event bubbles up to $('#container'), it checks to see if the event was a click and if the target element of that event matches the CSS selector. If both checks are true, it executes the function.
Notice this is similar to .live(), except that it binds the handler to the specified element instead of the document root. The astute JS’er might conclude that $('a').live() == $(document).delegate('a'), right? Well, no, not exactly.
Why .delegate() is better than .live()
jQuery’s delegate method is generally preferred to the live method for a few reasons. Consider the following examples:
// or
$(document).delegate('a', 'click', function() { blah() });
Speed
The latter is actually faster than the former, because the former first scans the entire document for all $('a') elements, storing them as jQuery objects. Even though the live function only needs to pass ‘a’ through as string argument to be evaluated later, the $() function doesn’t “know” that the chained method is going to be .live().
The delegate method on the other hand, only needs to find and store the $(document) element.
One hack to get around this is to call the live binding outside of the $(document).ready() state, so that it runs immediately. That way it will run before the DOM gets populated, and thus won’t find the elements or create the jQuery objects.
Flexibility and chain-ability
The live function is also convoluted. Think about it; it’s chained to the $('a') object set, but it’s actually acting on the $(document) object. For this reason, it can get hairy trying to chain methods to it. In fact, I’d argue the live method would make more sense as a global jQuery method in the form of $.live('a',...).
CSS selector only
And finally, the live method has a very large shortcoming, and that is that it can only operate on a direct CSS selector string. This makes it very inflexible.
For more on the CSS selector shortcoming, see Exploring jQuery .live() and .die().
Update: Thanks to pedalpete on Hacker News and Ellsass below in the comments for reminding me to add this next section.
Why .live() or .delegate() instead of .bind()
After all, bind seems so much clearer and more direct, doesn’t it? Well, there are 2 reasons we prefer delegate or live to bind:
- To attach handlers to DOM elements that may not yet exist in the DOM. Because
binddirectly binds handlers to the individual elements, it cannot bind them to elements that aren’t on the page yet. If you were to run$('a').bind(...), and then new links were added to the page via AJAX, your bind handler would not work for these.liveanddelegateon the other hand are bound to another ancestor node, so it will work for any element exists now or in the future within that ancestor element. - Or to attach a handler to a single element or small group of elements, listening for events on descendent elements, instead of looping through and attaching the same function to 100 individual elements in the DOM. This would be the performance benefit of attaching a handler to one (or a small group of) ancestor element(s) instead of directly attaching handlers to all elements on the page.
Stopping propagation
I’d like to mention one last note concerning event propagation. Typically, we can stop other handler functions from running by using event methods like:
e.preventDefault();
// or
e.stopPropagation();
});
However, when we use the live or delegate methods, the handler function won’t actually run until the event bubbles to the element to which the handler is actually bound. By this time, our other handler functions from .bind() have already run.

Very good explanation, Steve. Thanks for writing this post.
nice post. thanks for the write up.
One big difference is that
(and, I believe,
) will work on elements that are not present when the document loads. That is, if you do
it will not fire on any links that are added to the page later (e.g., via ajax). But
will work on all links at any time, whether they were there from the start or created later on.
Yes correct!
The .delegate() and .live() are used to bind the events which generates via ajax or later.
Ellsass: Yes! Holy crap, I can’t believe I glazed over that fact, I was so focused on explaining it technically, I forgot to mention the “why”. I’m updating the article now with a small “why delegate/live instead of bind”. Also see my comment on Hacker News concerning this.
how bout using
bind()like this? it’s a bit longer to write. but how’s the speed compare to usingdelegate()?var target = e.target;
if (target.tagName==='A') {
// do stuff
}
});
Rizky: that’s an interesting question. That is what
delegatedoes logically, though it isn’t how it’s implemented literally. If I had to hazard a guess without testing it, I’d say yours would probably both bind faster (due to use of.bind()) and execute faster (since you’re not using any CSS parsing). However, yours lacks the flexibility to do any more advanced CSS selectors, multiple selectors, etc. without changing your actual handler function.Also, take care to use the appropriate target (which you are), in terms of
e.targetvse.currentTargetvse.relatedTarget(see jQuery’s Event object for explanation).It will only be faster for a single bind. If you do multiple delegate will be faster.
It would only ever be a single bind though, because there is only one
$(document)root node.I mean if you wanted to do
if($(ev.target).closest('div')){...}
})
$(document).click(function(ev){
if($(ev.target).closest('a')){...}
})
Using delegate/live will be faster
Also, that example is not the same as live. It needs to check if the target is within an ‘a’ element. Consider clicking a span inside an ‘a’.
Thanks, very helpful! Had problems before with .bind events not being fired on elements that didn’t existed in the DOM from the beginning.
Very nice explanation! This is extremely helpful. I’ve used all three (and really like delegate), but I wasn’t exactly sure where it differed from .live(). Thanks.
Clean and helpful as usual.
I only use some classics binding with the no-xmlHTTPrequest elements, but always live() and also die() on elements from an ajax respond.
Never heard about delegate() method like this, thank’s for this great post.
Great job. Thanks for tackling this. It makes jQuery that much more inviting when functionality can be so easy explained.
Awesome! I didn’t know delegate(). That seems like a much nicer syntax.
By the way, in your note at then end,
e.preventDefault()will still work. Its job is to stop the browser from doing what it normally does in response to an event, like following a clicked link. That action doesn’t happen until all of the JS events are resolved, so we can still cancel it, even from a bubbled handler on document.Good point about preventDefault(). Though, I was referring to the fact that many people will use
e.isDefaultPrevented()in their other handlers to determine whether or not to execute their handlers. In that case,e.preventDefault()in adocumentbinding would still prevent the browser from doing it’s thing, but would not prevent their other handlers from executing, since their other handlers would have already been triggered by that point.Thanks Steve. Just what I was looking for. I’ve signed up for your feed. Question. What’s the difference between:
and
Hey Trevor, glad it helped. The difference is that the first function finds every
aelement within#containerand makes a collection of jQuery objects out of them, before simply passing theaselector string on to the.live()method.Meanwhile, the second function just turns
#containerinto a jQuery object, and passes theaselector string to the.delegate()method.If the first function has to search through a large DOM with lots of links, it will be much slower to initialize.
Am i missing something or
delegate()andlive()aren’t the same thing ? ( just look at the jquery code )- ps : please somehow change your spam protection engine. that fucking thing drives me crazy… that’s 5th time i trying to write comment-
http://code.jquery.com/jquery-1.5.1.js
delegate: function( selector, types, data, fn ) {
return this.live( types, data, fn, selector );
},
....
Hey, sorry about the aggressive spam filtering. I tried whitelisting you, but couldn’t find you in the blocked list. Let me know if it happens again and I’ll dig around.
Delegate and live are not the same thing for the reasons outlined in this post. The
livemethod that.delegate()references is a different function used internally within the jQuery source. You can see that method defined here, while the publicly available.live()method is defined here.Thanks for the explanation and links. After reading the code it’s now clear
Spam filtering : Now looks like everthing works. Somehow yesterday, i coudn’t write my comment without fighting
No prob, I remember that internal method tripped me up the first time I started patching the methods in jQuery. The thing that finally gave it away was that the internal method was called with 4 parameters while the public method accepts 2 parameters, the event and handler function.
Awesome article. I found another article which defines the difference between all 3 methods bind, live and delegate.
http://jquerybyexample.blogspot.com/2010/08/bind-vs-live-vs-delegate-function.html
http://jquerybyexample.blogspot.com/2010/08/bind-vs-live-vs-delegate-function.html
this link really a excellent bcz it gives clr ideas..thnx…
Great overview. Can you shed some light on why rails/jquery-ujs is using .live() instead of .delegate(). .delegate() seems to be a viable, maybe even better choice.
It’s using
.live()because I’m guessing the original author of the binding section was unaware of.delegate(), as is usually the case.Also, none of the downsides applied in this case. We’re only using CSS selectors, we don’t need to chain anything to the binding function, and as of this commit, we’re not waiting for the DOM ready event.
However, as I’ve pointed out here,
.delegate()is just generally better practice, so I’ll probably change it soon..delegate()in this thread.Just wanted to say “Thanks a lot.”, but it was rejected as too short.
Thanks man. I didn’t even realize I had a length limitation, I’ll have to look into that.
Excellent explanation…
Nice!!!!
Thank you very much Steve!
Hi,
Its just awesome. good that i found it when i started to learn about these.
Ur Face is good
Legend – thanks for that!
i need to call a jquery function with many actions.my jquery plugin supports only hover action, i saw the javascript file and found this:
$(this).hover(function() {…some code}
so is there a way to tweak this and use it to be called by onhover as well as onfocus??
Simply change that line to:
$(this).bind(‘hover focus’, function() { …some code }
excellent article, very concise and easy to read. Finally me – spoiled internet user lazy to read multipage manuals – understood this difference!
Thanks much, Steve
[...] Today @ 08.57 It's worth knowing that jQuery's live() and delegate() work by using event bubbling. And here's an explanation of the differences between bind(), live(), and delegate(). [...]
Nice article, also just wanted to clear that bind can be used for elements that are added after the original page load. You can create an element and bind it before adding it to the document.
You don’t even need to add the element to the document for bind() to work.
It is clearer to say that bind will only affect the matched element(s) retrieved by the CSS query at the time of the query. Or to be more exact will only “bind” the set of element(s) it is given (as you could use bind without a CSS query)
P.S: I know the example I give is not the same case as you are showing but I just wanted to illustrate that saying bind() doesn’t work on element added after the page load was unclear.
P.S2: Only problem with posts like this, is that many, if not most, of the readers will start using live() and delegate() over bind() for the wrong reasons.
I think this article could have done with more information on how to pick which method is best for your situation. live() and delegate() are only good to bind dynamic content, if your page doesn’t change it’s not needed and will actual damage performance. (also I am not sure the overhead done by delegate/live everytime something is clicked, is less than the overhead to loop over many elements and bind them individually the first time – performance over time)
That is correct,
.bind()works on the set of elements present at the time it’s called. I thought that was clear, but perhaps it could have been clearer.This is not true.
.live()and.bind()are not just for binding dynamic content, they’re good for binding basically any content, and especially when we have a lot of elements already on the page. And they do not damage performance compared to bind, in fact generally quite the opposite.They improve performance at bind time (by a large amount when there are a lot of matching elements), which can be done before the document is ready with live and delegate, which means the document loads faster. And they only add a tiny fraction of a performance hit when the person actually clicks or interacts with the element (and when I say tiny fraction, I mean basically imperceptible).
If you think about it, this makes sense. They improve performance at bind time, because they replace the necessity for
.bind()to potentially loop through tens, hundreds, or thousands, of objects, with only binding one function to one object to handle them all. And it only impacts performance very minutely on interaction, because it just needs to do a simple one-time comparison each time the person interacts (i.e. it’s not looping through anything or doing anything repetitively). The one-time comparison it does is usually negligible compared to the function you’re actually binding.“This is not true. .live() and .bind() are not just for binding dynamic content” Did you mean “live” and “bind” or “live” and “delegate”.
The second one.
Hi Steve,
Great explanation!
I would like the difference when we use:
Or is it the same of the .bind()?
Thanks!
Yes, in jquery,
.click()is just a shortcut for.bind('click').Another difference between bind() and live() / delegate() is that for each $(selector).live(type, handler) call, jQuery only calls handler on the $(event.target).closest(selector) element – that is, the nearest matching ancestor-or-self element of the event target.
(For more details see http://ejohn.org/blog/closestarray-in-jquery-14/)
This means that:
- $(“div”).live() can be different to $(“div”).bind() as the former only works for the closest div to the event target
- Similarly, $(“div, p”).live() can different to $(“div”).live(); $(“p”).live();
(This comment is largely copied from my somewhat dated stackoverflow answer http://stackoverflow.com/questions/2202367/what-is-the-difference-between-jquery-live-and-livequery-plugin/2204363#2204363)
Great Post. Thanks for the clear explanation. Keep up the good work!
excellent post. very helpful. thanks for sharing.
Nice clear and helpful explanation. It makes it very clear as when to use .live and when not to use it. The explanation of why delegate performs better over live is well described.
Deprecated..
http://blog.jquery.com/2011/09/28/jquery-1-7-beta-1-released/
I don’t think they’ve actually deprecated any of the existing methods of event-binding. In fact, from the linked post:
And the new API methods,
onandoff, still require an understanding of live, bind, and delegate, as described here. This new API still has the ability to bind in each of the different methods. The only difference is that you now pass in your preferred method of binding in the arguments to theonmethod, rather than using three different method names.Beautiful article.
Can you please provide examples as how .delegate works?
Whenever I’m using .delegate the following error pops up in firebug:
My code:
alert("Clicked on table header");
}
Proper code:
alert(“Clicked on table header”);
});
Note that
.delegate()was added in jQuery 1.4.2, so if you’re using an older version, you’ll need to update in order to use it.Got it.
I was using the .delegate inside .ready function.
I put it outside, now its working like magic !
Thank you.
I have a question though. I have been hearing and reading a lot about discontinuing usage of javascript and JQuery as a whole as these run at browser side,security issue and blah blah blah.
Is this true?
Glad you got it. And I had not heard of such talks.
Cool. Thanks for your inputs.
Very nice article Steve.
By starting off with the basics of the DOM event bubbling you’ve really made the explanation of bind(), live() and delegate() so much easier to grasp. Beforehand I just clumped them all together as “event handling stuff” with just the knowledge that bind() attached to existing DOM elements and live() could attach handlers to “future” elements but now I know why and also about delegate() too.
Of course the new .on() and .off() of jQuery 1.7 have simplified this but it’s good to know where the need for amalgamation of event handling came from too.
Thanks for taking the time to write this article Steve.
Thanks, I was binding a click event to the body element inside another click event and wondering why they were both firing. Your explanation made me realize that after the first one fired it bubbled up and triggered the second.
Love the way you wrote this blog post and you took care of a lot future queries while writing the blog itself
Thanx.
Hi,
lets say that i’m using ajaxForm on all my forms and the forms are created dynamically. So it’s not bound with an event**, I just want it to apply to the forms as it is created. Something like:
$(‘form’).magic(ajaxForm(options));
and then it runs $(‘form’).ajaxForm(options) and listen for new elements that matches $(‘form’), to run the same ajaxForm.
I’m not sure if I made myself clean. Is there a way to cope with what I want? Btw, excellent article.
** I mean, it’s not to be run in case a click happens, it must run when the element is created.
To clarify,
.ajaxForm()is from the form.js jquery plugin, not jquery itself. If you just want to bind to an element directly when it is added to the dom, you can just use.bind()when in your code that adds it to the dom.Excellent post! Very informative, Steve.
Thank you for the clarification between all of these events.
Would there be any chance we all could get your understanding in how the operation and mechanics of the ‘on’ event works compared to the other three events?
Yes, you can think of
onas a sort of meta-function that combines the functionality of all three (well, technicallyonis now the actual function,delegatedefers toon, andliveis deprecated). If you check out the docs linked at the top of the article, they have a table that compares the old API and the new API usingon.If you’re asking for my personal take, I still prefer using
bindanddelegate, since they’re much more expressive. The newondoes a good job of combining 3 different functions that all have closely related intents, but I don’t like that it conflates very different mechanics into almost identical syntax. When I’m writing JS code, I prefer to be able to quickly understand both intent and functionality (i.e. mechanics).Great article, makes it very clear what each does. Cheers!
Very nice explanation! Thanks from Brazil!
Excellent article, Steve. Your explanation was very clear and you made it easy to understand.
What you say about stopping propagation is not correct. For simple test case, have a document that has only one ‘a’ element.
Then attach two handlers:
$(‘body’).click(function (ev) { ev.stopPropagation(); });
$(‘a’).live(‘click’, function (ev) { alert(‘foobar’); });
Clicking the a-element won’t have an alert box.
I actually had this exact same conversation on Reddit a few days ago. You misinterpreted my note about
stopPropagation()not working. Sorry for the confusion, but what I mean by the statement that, callingstopPropagation()in a delegated handler is too late to actually stop it, is this:Very well explained, i don’t understand it completely though but that’s my problem. And wonderful article.
A Big Thanks
Nice and clear explanation…….
Great Job… Steve
Keep up the good work!!!
Very nice article ! Thanks for sharing it. I will use it for future reference, for sure
But I have two comments to do.
First of all, is it possible to update the article to mention the new
method and the deprecation of
since jQuery 1.7 ?
Secondly, the part about using
to “run [the code] before the DOM gets populated” is not accurate. Depending on where the script tag is positioned in the HTML source code, the usage of
is not needed. Check the demo on jsfiddle http://jsfiddle.net/pomeh/PYa9N/.
Cheers !
pomeh
Thanks for the comments. The article already has a mention of the new
$().onfunction at the top. The part about using$().liveoutside$(document).readyassumes the javascript is in a script in theheadsection of the document.Thanks for the reply.
In most cases, script tags should not be placed in the head section, this is considered as a bad practice. So I think this relation between
and
to “improve the speed” sounds like a bad shortcut and thus a bad advice to me. And this is also one of the reason why delegate is better and why live has been deprecated and will be removed in a future version.
If you’re talking strictly about script tags placed directly in your html document, then yes, but I was referring to javascript in an external javascript file, which is usually where you would write your javascript. And links to external js files are usually in the head section.