jQuery Best Practices

This article explains the things already known to us. In jQuery, we can do similar things in several ways. However, there are differences in performance of each approach. As a web developer, we need to use the best suitable approach for improving the performance.

I have used JSFiddle and jsPerf for demo purposes and also provided the links in respective sections. You need to click on the “Run Tests” button on “jsperf” to check the difference in performance. Sometimes, you may find the demo working to contradict with the article. But, nothing to worry about, since this happens due to network issues. So, just be patient and run it once again to see a proper response.

Use the latest version of jQuery

It's always good to use the latest jQuery version in your web application. But, some earlier plugins in your application might not be compatible with the latest version of jQuery. This issue is usually found in Internet Explorer (IE) and the compatibility issues may arise in IE8 or prior versions. IE8 or below are compatible with jQuery1.* versions. So, we need to have a mechanism to load jQuery1.11.2 (the latest in jQuery 1.*)  and for others the latest jQuery version.

  1. [if lt IE 9]  
  2. <script src=”http://code.jquery.com/jquery-1.11.2.js”></script>  
  3. [endif]  
  1. [if gte IE 9]  
  2. <script src=”http://code.jquery.com/jquery-2.1.3.js”></script>  
  3. [endif]  
If it's an Internet Explorer (IE) version less than 9 then jquery-1.11.2.js will be loaded. If it's greater than or equal to 9, jquery-2.1.3.js will be loaded. Here, we fixed an issue with IE. Now, other browsers will load both the jQuery files. However, the later will be put in effect, but unnecessarily we are loading 2 JavaScript files that will cost our site's performance.

Here is a syntax designed by Microsoft that is only understood by Internet Explorer. We can get its help to avoid the preceding issue.
  1. <!--[if lt IE 9]>  
  2. <script src=”http://code.jquery.com/jquery-1.11.2.js”></script>  
  3. <![endif]-->  
  1. <!--[if gte IE 9]><!-->  
  2. <script src=”http://code.jquery.com/jquery-2.1.3.js”></script>  
  3. <!--<![endif]-->  
Browsers other than IE just can't understand the first block. So, the first if-block will be ignored (considered as white space). In the second if block, the script tag is outside the comment. So, its easier for the web browsers to understand.

Web browsers other than IE will read it as:
  1. <!--  
  2. <script src=”http://code.jquery.com/jquery-1.11.2.js”></script>  
  3. - ->   
  4. <!-- -->  
  5. <script src=”http://code.jquery.com/jquery-2.1.3.js”></script>  
  6. <!-- -->   
So, IE will load jQuery based on the IE version and the condition specified. IE 8 or less will load jquery-1.11.2.js and IE9 or more and other browsers will load jquery-2.1.3.js.

Use CDN

It's always a good practice to use Content Delivery Network (CDN) over local jQuery files. But, what if CDN is down? Your site will not function properly. Not to worry, we have a way to overcome it.

Load the jQuery file from CDN. Check if it's loaded or not; load it from local, if it's not yet loaded. Here's the code.
  1. <script src=”http://code.jquery.com/jquery-2.1.3.js”></script>  
  2. <script>  
  3. window.jQuery || document.write('<script src=”~/Js/jquery-2.1.3.js”><\/script>')  
  4. </script>  
Selector Preference
  1. Try to use ID since it gives the best performance $('#elementId').
  2. Performance-wise, next comes the tag selector $('tag').
  3. Avoid selection by class. Class selectors are the slowest $('.elementClass').
  4. If you need to use a class selector, use it with it's tag or parent elements.
  1. $('div.myClass')  

Increase specificity from left to right, not right to left.

Use:

  1. $('div#divTest p')   
Instead of:
  1. $('p', $('div#divTest'))  
$.find()
  1. Use find() instead of specifying the context explicitly.  
Use:
  1. $('#Mydiv').find('label.myClass').hide()   
Instead of:
  1. $('#Mydiv label.myClass').hide()  
The preceding code will provide the same result, but the former one is faster.

find method

jQuery uses the Sizzle engine for pseudo classes like :not and :last. Try not to force jQuery to use it.
 
Cache the Selector

When you need to perform some jQuery operations on a specific element, it's better to keep the selected element in a JavaScript variable and operate on it, instead of getting the required element each time you need to operate on it.

Instead of:
  1. $('#Mydiv label.myClass').html('My label');  
  2. $('#Mydiv label.myClass').css('border','1px solid red');  
  3. $('#Mydiv label.myClass').show();  
Use:
  1. var SelElement = $('#Mydiv label.myClass');   
  2. SelElement.html('My label');  
  3. SelElement.css('border','1px solid red');  
  4. SelElement.show();  
cache selector

Chaining

Take advantage of jQuery chaining. You can perform multiple jQuery operations on the selected element at once in a single line. It is faster than performing operations one-by-one.

Instead of
  1. var SelElement = $('#Mydiv label.myClass');   
  2. SelElement.html('My label');  
  3. SelElement.css('border','1px solid red');  
  4. SelElement.show();
Use
  1. $('#Mydiv label.myClass').html('My label').css('border','1px solid red').show();

GroupUp Selectors

When you need to perform same operation on a list of elements, it's always recommended to group those elements and operate on the group.

Instead of:
  1. $('#divTest').hide();  
  2. $('p').hide();  
  3. $('label.myClass').hide();  
Use:
  1. $('#divTest, p, label.myClass').hide();  
Groupping

DOM Manipulation

When you need to add some elements to the DOM, it's always a good idea to form the entire HTML first, then add to the DOM, instead of appending the HTML step-by-step.
  1. <div id='myDiv'></div>  
  2.   
  3. var Details = [  
  4. {Id:1, Name: “ABC”, Standard:1},  
  5. {Id:2, Name: “MNO”, Standard:1},  
  6. {Id:3, Name: “PQR”, Standard:2},  
  7. {Id:4, Name: “STU”, Standard:5},  
  8. {Id:5, Name: “XYZ”, Standard:9}  
  9. ];  
  10.   
  11. var Element = $('#myDiv');  
Instead of:
  1. Element.append('<table>');  
  2. $.each(Details, function(k,v){  
  3. Element.append('<tr>');  
  4. Element.append('<td>' + v.Id + '</td>');  
  5. Element.append('<td>' + v.Name + '</td>');  
  6. Element.append('<td>' + v. Standard + '</td>');  
  7. Element.append('</tr>');  
  8. });  
  9. Element.append('</table>');  
Use:
  1. var strHtml = '<table>';  
  2. $.each(Details, function(k,v){  
  3. strHtml += '<tr>';  
  4. strHtml += '<td>' + v.Id + '</td>';  
  5. strHtml += '<td>' + v.Name + '</td>';  
  6. strHtml += '<td>' + v. Standard + '</td>';  
  7. strHtml += '</tr>';  
  8. });  
  9. strHtml += '</table>';  
  10. Element.html(strHtml);  
Dom manipulation

$.detach(), hide(), empty(), remove()

detach() is a new jQuery function. It will just detach the selected element from the DOM. The element, all it's properties and events are still there, but you can't use it. Don't be confused with hide(), empty(), remove() and so on. Here is a comparison.
  • Hide makes display:none. But the element is still there in DOM.
  • In case of detach(), the element is no longer there in the DOM, but it exists. All it's properties, attributes, events and so on are still attached with the element. When there is a need, you can again append it to it's parent or wherever you want to.
  • empty() removes child elements of the selected element.
  • remove() removes the elements themselves and hence all it's child elements are also removed.
  1. var MyTable = $('#MyTable');  
  2. var ParentElement = MyTable.parent();  
  3. MyTable.detach();  
  4. // Operate on the table  
  5. …. 
ParentElement.append(MyTable);

Group Up your CSS

When you have a set of styles to apply on some elements, it's always recommended to group up all the styles and apply on the element at once.
  1. Var MyDiv = $('#MyDiv');  
  2. Instead of  
  3. MyDiv.css('border''1px solid black');   
  4. MyDiv.css('color''red');   
  5. MyDiv.css('backgroun-color''green');   
  6. MyDiv.css('display''block');  
Use:
  1. MyDiv.css({'border''1px solid black''color''red''backgroun-color''green''display''block'});  
Group Style

Instead of:
  1. MyDiv.css('backgroun-color''white');  
  2. if(Cond)  
  3. {  
  4. MyDiv.css({ 'color''red''border''1px solid red'});  
  5. }  
  6. else  
  7. {  
  8. MyDiv.css({ 'color''green''border''1px solid green'});  
  9. }  
Use:
  1. var Css = {'backgroun-color''white'}  
  2. if(Cond)  
  3. {  
  4. Css .color = 'red';  
  5. Css.border = '1px solid red';  
  6. }  
  7. else  
  8. {  
  9. Css .color = 'green';  
  10. Css.border = '1px solid green';  
  11. }  
  12. MyDiv.css( Css);  
Style is better than CSS

css() works fine when you need to put style on fewer elements. But, when you need to put a specific style on more than 20 elements, a style in the head tag will provide better performance than adding CSS.

Instead of:
  1. $('div').css({ 'color''red','width''200px','height''200px',  
  2. 'border''1px solid','margin-left''10px','position''relative','display''block'  
  3. });  
  4. Use  
  5. $("<style type=\"text/css\">div { color: red,\width: 200px,\height: 200px,\  
  6. border: 1px solid,\margin-left: 10px,\position: relative,\display: block }</style>")  
  7. .appendTo("head");  
Style vs CSS

Event Delegation/Propagation
  1. <div id='divOuter' style='border:1px solid red; width:500px; height:300px;'> divOuter  
  2. <div id='divMiddle' style='border:1px solid green; width:400px; height:200px;'> divMiddle  
  3. <div id='divInner' style='border:1px solid blue; width:300px; height:100px;'> divInner</div>  
  4. </div>  
  5. </div>  
  6.   
  7. $('div').click(function(){  
  8. alert($(this).attr('id'));  
  9. });  
Rasmitadash

If you click on the inner-most div, you will get 3 alerts. If you click on the middle div, you will get 2 alerts. If you click on the outer-most div you will get a single alert. This is because when you fire an event, it propagates to it's parent, then the parent's parent ... and finally to the root. That means, when you click an element, you are effectively clicking the entire document. This is called event bubbling or propagation.

We have a way to prevent this event propagation.
  1. $('div').click(function(e){  
  2. e.stopPropagation()  
  3. alert($(this).text());  
  4. });  
hr2 gamp

Bind Event dynamically

There are several ways to bind an event to an element dynamically; .bind(), .on() and .delegate().

.bind()
  1. $('#ulItems li label').bind('click'function(){  
  2. alert($(this).text());  
  3. });  
The shorthand representation of .bind() is as follows.
  1. $('#ulItems li label').click(function(){  
  2. alert($(this).text());  
  3. });  
  1. bind() attaches the event upfront. So, it can have performance issues on page load.
  2. bind() not only wires up quickly, but the event handler is invoked immediately when the event is fired.
  3. bind() will not attach the event handler to the dynamically added matching elements.

.delegate()

  1. $('#ulItems').delegate(' li label''click'function(){  
  2. alert($(this).text());  
  3. });  
  1. delegate() attaches events to the root level element (here #ulItems) and to the selected elements as well. When an event is bubbled or delegated or propagated to a parent element, jQuery checks the event metadata to determine which event handler should be invoked. This extra work makes the performance slower with respect to user interaction.
  2. The event bind is not done upfront. So, initial registration process is speedy.
  3. As event is bound to the parent element, therefore it affects the dynamically bound elements as well.

.on()

  1. .on() can mimic for .bind(), .delegate(), .live(). It's behavior depends on the parameters ed.  
  2. $('#ulItems').on('click'' li label'function(){}); => $('#ulItems').delegate(' li label''click'function(){});  
  3. $('#ulItems li label').on('click'function(){}); => $('#ulItems li label').bind('click'function(){});  
Event delegation
  1. <div>  
  2. <ul id='ulItems'>  
  3. <li><label>Item #1</label></li>  
  4. <li><label>Item #2</label></li>  
  5. <li><label>Item #3</label></li>  
  6. </ul>  
  7. </div>  
  8.   
  9. $('#ulItems li label').click(function(){  
  10. alert($(this).text());  
  11. });  
  12.   
  13. Now, let's add a 'li' element.  
  14. $('#ulItems').append('<li><label>Item #4</label></li>');  
http://jsfiddle.net/rasmitadash/k7435o18/

Now, when you click on this newly added label, you will not get any alert. Because, when you registered this event, the element was not there, it was added after the event was registered.

To make the dynamically bound events effective on dynamically bound elements, bind an event to the parent element and delegate it to the required element. Let us see an example. 
  1. $('#ulItems').delegate(' li label''click'function(){  
  2. alert($(this).text());  
  3. }); 
http://jsfiddle.net/rasmitadash/vwp2erxc/

ing data to Event handler
  1. function Greet(event)  
  2. {  
  3. alert(event.data.name)  
  4. }  
  5.   
  6. $('#ulItems li label').click({name: “Rasmita”}, Greet);  
rasmitadash

Binding multiple Events
  1. $('#Mydiv').on({  
  2. click: function(){  
  3. alert(“clicked”);  
  4. },  
  5. mouseenter: function(){  
  6. alert(“mouse enterd”);  
  7. },  
  8. mouseleave: function(){  
  9. alert(“mouse left”);  
  10. }  
  11. });  
rasmitadash

attr() vs prop()
  • An attribute value may only be a string, whereas a property can be of any type. For example, the”checked”property is a Boolean, the”style” property is an object with individual properties for each style, the “size”property is a number.
  • If a property and attribute have the same name, usually updating one will update the other, but this is not the case for certain attributes of inputs, such as “value” and “checked”. For these attributes, the property always represents the current state, whereas the attribute (except in old versions of IE) corresponds to the default value of the input.

So, “attribute value” holds the default value of the input control. If the user changes a value, the “property value” changes, but not the “attribute value”. Therefore, for a default value we use the .attr() function and for the latest value of HTML elements (such as inputs, checkbox's, radios and so on) use the .prop() function.

rasmitadash etz3

Binding events in loop

Avoid implementing an event handler body with the event itself. Instead, create a separate handler function and call the handler with a parameter.

rasmitadashq8714
rasmitadash7awz6

Instead of:

  1. $(function(){  
  2. var ArrLabel = $('label'), len = ArrLabel.length;   
  3. for(i=0; i<len;i++){  
  4. $(ArrLabel[i]).on('click',function(){  
  5. alert(i);  
  6. });  
  7. }  
  8. }); // This will always give final value of 'i'  
Use:
  1. $(function(){  
  2. function myclickhandler(j){  
  3. return function(){  
  4. alert(j);  
  5. }  
  6. }  
  7.   
  8. var ArrLabel = $('label'), len = ArrLabel.length;   
  9. for(i=0; i<len;i++){  
  10. $(ArrLabel[i]).on('click',myclickhandler(i +1));  
  11. }  
  12. }); // This will give the expected value of 'i'