is there a difference between the jquery code here? - javascript

Here is the code block a
$('ul.filter li').each(function() {
$(this).click(function(e) { //do something });
});
Here is code block b
$('ul.filter li').click(function(e) { //do something });
Don't these do the same thing? is one better than the other? Which one is the better/faster method?
I would assume block b since it has less code but I want to confirm it here, thanks

The effect you see will be the same, but in the first case, every li element is assigned a new function, as you are creating the function object inside the each callback.
In the second case, there exists only one copy of the event handler, which means it uses less memory over all (although this is probably not measurable).
Internally, click calls on (in jQuery 1.7), which is iterating over the elements via each as well:
return this.each( function() {
jQuery.event.add( this, types, fn, data, selector );
});
This is the case with many jQuery methods (most often noted in the documentation), so you are saving characters and memory by letting jQuery implicitly do this.

They would both have the same effect.
I would prefer the second only because it is more concise and you're creating a single anonymous function to handle the click rather than an anonymous function per element.

For Jquery philosophy, the second is better because it is shorter.

Both are more or less same and give the same results. The second code snippet will also internally run each loop and assign the click handler to each li element.
But yes the second code snippet is very clear and simple.

The second usage is called "implicit iteration" and is one of the cornerstones of jQuery.
For example, in JavaScript Definitive Guide, 6th Ed, p.530 for jQuery Basics:
Despite the power of the each() method, it is not very commonly used,
since jQuery methods usually iterate implicitly over the set of
matched elements and operate on them all. You typically only need to
use each() if you need to manipulate the matched elements in
different ways. Even then, you may not need to call each(), since a
number of jQuery methods allow you to pass a callback function.
in http://jqfundamentals.com/chapter/jquery-basics
Implicit iteration means that jQuery automatically iterates over all
the elements in a selection when you call a setter method on that
selection. This means that, when you want to do something to all of
the elements in a selection, you don't have to call a setter method on
every item in your selection — you just call the method on the
selection itself, and jQuery iterates over the elements for you.
Typically, when the library has this built-in as the standard way of doing it, it will be in general better and faster, or else they wouldn't have built it in.

Related

jQuery: better performance with check whether binding element exists?

I wonder... Let's imagine I have a code something like that:
$('#specific-element').change(some_long_and_ajax_function);
Element with binded ID doesn't exist on all of my pages. On some of them only. I do check whether this element exists like this:
if($('#specific-element').length > 0){
$('#specific-element').change(some_long_and_ajax_function);
// There can be more stuff related to this specific element
}
My question: is it worth it? Is there any performance impact for binding handlers for non-existing elements or checking length is worse than it? Or is it basically same and I have two useless rows? What would you recommend? The first one keeps code nice and clear but I'm not sure if this will be "healthy" for jQuery with dozens of examples like that. Thanks.
jQuery fails gracefully if the element doesn't exist, internally it does it's own check to see if the element exists, and if it doesn't the event handler isn't attached etc.
jQuery() calls jQuery.fn.init wich checks if the passed argument is a string, which in your case it is, it then calls jQuery.fn.find with the right context, and inside that it does
var i, ret = [],
self = this,
len = self.length;
... code
for (i = 0; i < len; i++) {
// add event handlers
}
so the loop never runs if there are no elements to run it on, so there's no need to do your own check, just let jQuery handle it.
EDIT:
When you call $('#specific-element').length you're already calling $(), and it does all the usual things internally and returns an array-like jQuery object that has a length property, and that's exactly what $('#specific-element').change... does as well, and jQuery's on() also returns rather quickly if no elements exists in the collection, so there really is no difference.
If you're really concerned about speed, you'd do something like
var el = document.getElementById('specific-element');
if ( el !== null ) {
el.addEventListener('change', fn, false);
}
but there's really no reason, just add event handler with jQuery the usual way, without checking it the element exists, it's what almost every website in existance does, and it works just fine.
As said in the comment, jQuery check if the element exist before binding events. But there is a speed difference wether you check or not.
When checking before binding, you save time if the element doesn't exist because getting a property (.length) is way faster than calling a function (which will probably call other functions) and failing gracefully.
But if the element exist, it will be slower since you add a condition before binding. Hence, it add 1 more step than if you did not check before and directly binded the event.
Just interpret those test results : http://jsperf.com/check-before-binding1
You can see that if the element exist, the difference between the check before is only 4000 operations / second more. It is not a lot... On the other hand, when you check if the element exist and it doesn't, it save 1,000,000 operations / second because it doesn't call the function .change().
Conclusion
I'd say checking before is better if that really matter, but mostly, it doesn't. If the element is most often present than missing on different pages, i'd directly bind the event. If the element is mostly missing than present, i'd check before binding.
In the end, we are talking about 0.0000001ms...
1I have slightly changed to code to optimise your. Caching the element sure is important is you want better performances.

How does jQuery act on multiple selectors?

I've been wondering for a little while how jQuery acts on multiple selectors. For instance:
$("p").css({"border":"1px solid #000"});
Performs the subsequent function on all p tags. I've had a look through the jQuery source but to be honest it's an extensive read when you're trying to work out one specific bit of functionality. My assumption is that there's some kind of stack whereby css() and other functions merely act on the current stack, which is divined by the selector function.
Other than that, I can't work out how it could be replicated as, I think, there's no way in javascript to return multiple objects to execute a function on. E.g.
House.first_bedroom.size = "large"
House.second_bedroom.size = "small"
House.all_rooms().alertSize();
alertSize() would have to be a member function of some collection of objects rather than a member function of each room object that is returned by all_rooms()?
First, jQuery functions (generally) return a jQuery object, which acts like an array and keeps track of the current set of matched elements. Second, internally each jQuery function makes extensive use of the each() function to iterate over the matched objects, perform subsequent actions and construct the new jQuery object to return. Some functions do return something other than jQuery, like get(). These functions cannot be chained. Chaining is only possible when the function returns a jQuery object. Because the returned object is a jQuery object it has all the functions of jQuery available to it.
The jquery constructor ($(...)) always return a jquery object. You can think of it as a fancy array. The items selected are stored (looks like this is called context in the source).
So then on your object you're calling the function css... See jQuery.fn.css in the source. It basically calls a function which performs the delegate (setting or getting the css) on each item in the context.
Perhaps the DOM is parsed and all elements matching the criteria are added to an array? Or.. something more efficient? :)
Similarly, for event handling, a handler is assigned to each element in the array?
I'm just stabbing in the dark here.

Most efficient way to re-use jQuery-selected elements

I can imagine the correct answer to this based on theory, but I'm just looking for some confirmation. I'm wondering what the most efficient way to re-use a jQuery-selected element is. For example:
$('#my_div').css('background','red');
//some other code
$('#my_div').attr('name','Red Div');
vs.
myDiv = $('#my_div');
myDiv.css('background','red');
//some other code
myDiv.attr('name','Red Div');
I assume the second example is more efficient because the element #my_div doesn't have to get found more than once. Is that correct?
Similarly, is it more efficient to first save $(this) in a varaible, such as 'obj', and then reuse 'obj' rather than using $(this) over and over? In this case, jQuery isn't being forced to find an element over and over again, but it IS being forced to convert this to a jQuery object [$(this)]. So as a general rule of thumb, should a jQuery object ALWAYS be stored in a variable if it will be used more than once?
You should write your code such that you limit the number of DOM traversals.
When you write something like this:
$('#my_div').css('background','red');
//some other code
$('#my_div').attr('name','Red Div');
You are finding #my_div twice, which is inefficient.
You can improve this either by assigning the result of a selector (i.e. var x = $('.something')) and manipulate the variable x, or you can chain your method calls like this:
$('#my_div').css('background','red').attr('name','Red Div');
You'll see the above code used a lot, because you're finding the element once. The css() method will apply a CSS style and return the actual result of $('#my_div'), so you can invoke another method, in this case attr().
My preferred way of handling the re-use of selectors is to store them as a variable, and wrap my stuff in a closure.
if you're using jQuery selector (like $('#element')), then yes, you should always store your results.
if you're using object and wrapping it in jQuery (like $(this)), it's not necessary, because jQuery doesn't need to search for that element again.
One thing that I find is generally overlooked is just how powerful jQuery chains are. It may not be so noticeable, but since jQuery caches your wrapped elements within a chain, you can modify elements, go into a more specific subset, modify, then go back up into a a general superset without much overhead.
I expect something like (pardon the example)
$('#myDiv')
.addClass('processing')
.find('#myInput')
.hide('slow')
.end()
.removeClass('processing')
;
to be better performance-wise than even
var $myDiv = $('#myDiv').addClass('processing');
var $myInput = $('#myDiv #myInput').hide('slow');
$myDiv.removeClass('processing');
This also holds for applying the jQuery function to elements returned in an event handler. Try to avoid applying $(...) too many times, because this is slow. Instead create a variable that contains the result of $(...). Good practice is to start the variable with a $, which gives a hint about the jQuery object inside the variable.
$('a').click(function(){
var $this = $(this);
$this.addClass("clicked");
$this.attr("clicked", true);
});

jQuery performance: $('#selector').live() vs manually bind (when working with ajax requests)

When working with content loaded asynchronously is there any difference from a performance point of view between:
// .live()
$('#mybutton').live('click', function(e){ doSomething(); });
and manually bind() the events we need every time after the content has been loaded:
// manual bind every time
$.ajax({
url: url,
success: function(data){
mycontainer.html(data); // data contains #mybutton
$('#mybutton').click(function(e){ doSomething(); });
}
});
?
There are different costs, let's look at them:
$('#mybutton').live('click', function(e){ doSomething(); });
There are 2 main costs here:
The #mybutton selector needs to run immediately for no reason (the result is thrown away, we just wanted the selector anyway...we're binding to document). In this case it's an #id selector so that's a very low cost...in other cases it's not cheap and very wasteful (for example [attr=something]).
Every click that bubbles up to document now has to be checked against this selector, a per-click evaluation cost, this varies with the number of clicks you expect.
Now let's look at the other method:
$('#mybutton').click(function(e){ doSomething(); });
There are 2 main costs here as well:
The #mybutton selector runs, but only once per ajax request. However, we're not wasting it, we're using the results.
The click handler is bound to an actual element, rather than document, so there's a binding cost each time it runs, rather than once
However, there's no per-click cost and the selector call itself isn't wasted...so it's better overall, since you're using an ID, this isn't true in other cases.
In your case, since you're dealing with an ID (and guaranteed a single element), this is much cheaper:
$('#mybutton').click(function(e){ doSomething(); });
In other cases, where you're binding hundreds of elements, .live() is the clear winner, though .delegate() would be even better.
Probably a little, but I wouldn't worry about it. To me the .live() method looks much easier to maintain, so I would use that. As long as nothing's going painfully slow there's no need to worry about performance in JavaScript.
From the looks of your success function, you're attaching an event because that element is now available in your html? Is that so?
If that is the case, then if the function called via the click is always the same then you can use 'live'. Live lets you bind to events that don't yet exist. So you can put this in even before your document.ready. Then as the ajax updates your main document, that event should always work. You won't need to assign it every time.
So you get the performance benefit of not having to do something every time you return from an ajax call, you do the setup without relying on document.ready and its guaranteed to work.
HTH.

Why do I have to use $(this)? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
jQuery $(this) vs this
In jquery sometimes I find that within a function I have to use $(this) because this won't work:
var listItems = $('li');
listItems.each(function(index) {
$(this).css({
})
})
Any ideas as to the reason why?
$() is the jQuery constructor function
this is a reference to the DOM element of invocation
So basically, you're turning a DOM reference into a jQuery object
In your example, you could also use
listItems.each(function(index, element){
$(element).css({
});
});
..since .each() will pass both, index + element in its callback.
I know I'm a bit late to this thread but I just wanted to bring up the fact that redundant wrapping of DOM objects is one of the most frequently committed crimes against jQuery. Taking care with your jQuery-instance constructing can have tremendous effects performance-wise and it's so easy to do that you have no excuse not to.
Typically, when people have a DOM object (whether it be referenced as this or element) they'll try to wrap it each time they need access to a jQuery method:
jQuery(this).css('a', 'b');
The problem is when you're doing this multiple times:
jQuery(this).css('a', 'b');
jQuery(this).find('span').attr(...);
jQuery(this)....
Every time jQuery() is called, a new jQuery instance is constructed. That kind of operation is expensive and should be avoided if at all possible -- especially in loops!
To avoid this, for one, you could utilise chaining with all methods that return a jQuery instance $(this).css(a,b).attr(a,b)...). The rest of the time you should have a locally declared variable that refers to the jQuery instance and then just use that:
var self = jQuery(this);
self.css(...);
self.attr(...);
If you're doing this within an .each() callback function, there is still a new jQuery object being constructed on every single iteration. You can avoid this by having one generic jQuery object which you continually mutate and then you can run jQuery methods off that single instance:
Look at this:
jQuery.single = function(a){
return function(b){
a[0] = b;
return a
}
}(jQuery([1]));
Now look at this:
$('a').each(function(i){
$.single(this).append('Anchor number ' + i);
});
Only one jQuery object is being used. You can make it even faster by avoiding the identifier resolution:
$_ = $.single;
$('a').each(function(i){
$_(this).append('Anchor number ' + i);
});
Food for thought. More info here: http://james.padolsey.com/javascript/76-bytes-for-faster-jquery/
this is the native DOM element. $(this) is a jQuery object that allows you to call functions such as .css() on it.
this is typically a DOM object by default, which means it only has the methods on normal DOM objects.
If you want to invoke a library-specific function (such as jQuery's .css function), you have to convert it to a full jQuery object first, which is what $() does by default if you pass it a DOM object.
(You can also pass other things to $(), such as an HTML string (to construct a new jQuery-wrapped DOM object) or a CSS selector (to get a set of jQuery objects that correspond to DOM objects matching the selector).
If you are using Firefox, try console.log($(this)) and console.log(this) to see the difference.

Categories