There are number of ways to achieve a task in jQuery but knowing what to use and when to use a particular, separates you from other developers. This article contains some basic guidance that every jQuery Developer must keep in mind while working on their projects and websites.
1. stopPropagation or preventDefault or return false?
Developers new to stopPropagation, preventDefault and return false are often confused with which technique to use and when. This section will clear that confusion.
stopPropagation()
To understand stopPropagation, we need to understand event bubbling first. Let’s take an example. Let us say you have a link <a> inside a <div> as shown here:
<div id="divone">
<a href="#" id="aone">Click me</a>
</div>
The click event is hooked on both the link and the div:
$("#divone").click(function (e) {
alert("div clicked");
});
$("a").click(function (e) {
alert("link clicked");
});
When you click the link, the click() event fires and a function runs which displays "link clicked" in an alert box. The event however, doesn’t stop there. You will see another alert box which says "div clicked". In other words, even though you clicked the <a>, the <div> being its ancestor element, also receives the click event. This is called event bubbling or event propagation.
So in order to stop the event from bubbling, you use stopPropagation in the following manner:
$("a").click(function (e) {
alert("link clicked");
e.stopPropagation();
});
Now when you click the link, the click event will fire and a function will run that displays "link clicked" in an alert box. However due to e.stopPropagation, the event won’t bubble up. That’s why you won’t see the second alert box.
preventDefault()
If you want to prevent the web browser’s normal response to an event, use preventDefault(). By default, when you click on the hyperlink, the normal response of the event is to transfer you to the url represented in the hyperlinks href attribute. Let’s take the same example again. Define the hyperlink inside the div as follows:
<div id="divone">
<a href="http://www.jquerycookbook.com" id="aone">Click me</a>
</div>
Here clicking on the hyperlink transfers you to my new book’s homepage www.jquerycookbook.com. If you want to prevent this default behavior, use preventDefault() as shown here:
$("#divone").click(function (e) {
alert("div clicked");
});
$("a").click(function (e) {
e.preventDefault();
});
When you run the code now, you will see that clicking the hyperlink does not transfer you to the website as we have prevented the browser’s default action of the event.
However the “div clicked” alert does fire, as we are preventing the default, but not stopping event bubbling/propogation from occurring. If you want event bubbling from occurring too, then use both as shown here:
$("a").click(function (e) {
e.stopPropagation();
e.preventDefault();
});
Now we are doing both, so the browser doesn't follow the link and the div doesn't fire the event, hence we see no alert() box.
return false
return false is effectively a shortcut for calling stopPropagation() and preventDefault(). It is a way of telling jQuery to prevent the default and stop bubbling. Most of the times, you wouldn’t want to call stopPropagation, so I strongly advise that instead of using return false, use preventDefault() in your code.
2 - Some Selector Tips
Here are some selector tips that you can use to improve selector performance:
a. When possible, use the ID selector to select elements in your code.
b. Do not prepend the tag name before the selector. So if you have the following:
<input type="text" id="code" value="54325454" />
..do not use $("input#code"), rather use $("#code").
c. Wherever possible, use the method over a filter for better performance. So instead of $( "div:has(p)") you can use $("div").has('p'). Here .has() uses the native DOM querySelectorAll() method and hence is theoretically faster than :has.
d. Instead of using :lt and :gt selectors, use slice() instead.
e. It is recommended to precede a pseudo selector like :text with a tag name or some other selector; otherwise, the universal selector ( "*" ) is implied. In other words, $(":text") is equivalent to $( "*:text"), so $("input:text") should be used instead.
f. Instead of the Attribute Not Equal Selector, use .not() wherever possible for a slight performance advantage.
g. Instead of filters, use their equivalent attribute selectors. Eg: use $('[type=image]' instead of $(':image')
Further Reading:
http://learn.jquery.com/performance/optimize-selectors/
http://api.jquery.com/?s=selectors
3 - Use attr() or prop()
attr() deals with attributes while prop() deals with properties. Consider this markup:
<input type="text" value="original" />
The input field has the attribute "value". This is the default value you entered and this attribute does not update itself when the user interacts with it. So if the user changes the value in the input field, it is the property "value" that changes in the DOM Tree and not the attribute "value".
I have set up a jsfiddle demo to understand the difference between the two: http://jsfiddle.net/jquerycookbook/s1gsLcLb/
Run the demo and once you change the values of the textbox from “original” to something else, hit tab. You will see that attr() will return the original value but prop() returns the changed value.
So attributes do not change, but properties can be changed in the background by a user action (checking/unchecking a checkbox) or programmatically.
So when to use what? If you want to setup the default value for an HTML’s tag attribute, use attr(). However when you are setting properties on the window or document objects, you should always use prop().
Although I used this textbox example for explanation purposes, in true sense, neither .attr() nor .prop() should be used for getting/setting value. You should use the .val() method instead.
Before jQuery 1.6, we just had attr().
Further Reading: http://blog.jquery.com/2011/05/12/jquery-1-6-1-released/
4 - <script> in head or body?
In an HTML file, you can refer to your JavaScript at two places - within the <head>, or just before the closing </body> tag. The web browser processes an HTML page from top to bottom, and executes any JavaScript that it finds between <script> tags, along the way. Due to this, the loading of the page is blocked if one of your scripts takes time to execute. Therefore, it's better to put the scripts just before the closing tag of body element, which ensures that your script is run, after the DOM is loaded.
In some of my articles and even my book, I often chose to put the script inside the <head> tag, but this is only for the sake of readability. But I also make sure to use $(document).ready() or the shortcut $(function(){ }) which ensures that the script will be executed only when the browser has loaded all of the content in the HTML document. Hence I am achieving the same effect as that of putting the script just before the closing </body> tag.
Having said that, keep in mind that by having your scripts at the bottom of the page, you can completely avoid the use of $(document).ready(). In fact, in all my production ready applications, I use my scripts at the bottom of the page.
5 - Difference between this, $this and $(this)
Let us understand the difference between this, $this and $(this) with an example. Consider the following code:
$('div').each(function () {
var $this = $(this);
$this.css("background-color", "blue");
$this.slideUp('3000');
$this.slideDown('3000');
});
Here we are looping over a bunch of div’s using each(). Once you are inside the loop, this refers to the DOM element which is not a jQuery object. So to make it a jQuery object and to run jQuery methods on it, we do $(this).
Now look at this statement: var $this = $(this);
If you’re going to reference the DOM element multiple times in the code, which we are doing in our example; then for performance sake, you should get a jQuery reference to it and then save that to a variable. Here $this is that variable. This is also called as caching the selector as it is expensive to run the jQuery function $(this) each time. So storing the output in a variable allows you to re-use the selector over and over, without calling the jQuery function again.
Note: Don’t get confused with $this. You can call it anything you like. I usually refer to variables that contain jQuery objects as $variablename.
I hope these tips helped! You can also check out several other performance tips in my new book www.jquerycookbook.com
This article has been editorially reviewed by Suprotim Agarwal.
C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.
We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).
Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.
Click here to Explore the Table of Contents or Download Sample Chapters!
Was this article worth reading? Share it with fellow developers too. Thanks!
Suprotim Agarwal, MCSD, MCAD, MCDBA, MCSE, is the founder of
DotNetCurry,
DNC Magazine for Developers,
SQLServerCurry and
DevCurry. He has also authored a couple of books
51 Recipes using jQuery with ASP.NET Controls and
The Absolutely Awesome jQuery CookBook.
Suprotim has received the prestigious Microsoft MVP award for Sixteen consecutive years. In a professional capacity, he is the CEO of A2Z Knowledge Visuals Pvt Ltd, a digital group that offers Digital Marketing and Branding services to businesses, both in a start-up and enterprise environment.
Get in touch with him on Twitter @suprotimagarwal or at LinkedIn