jQuery pitfalls to avoid [closed]

I am starting a project with jQuery.

What pitfalls/errors/misconceptions/abuses/misuses did you have in your jQuery project?

Answers:

Answer

Being unaware of the performance hit and overusing selectors instead of assigning them to local variables. For example:-

$('#button').click(function() {
    $('#label').method();
    $('#label').method2();
    $('#label').css('background-color', 'red');
});

Rather than:-

$('#button').click(function() {
    var $label = $('#label');
    $label.method();
    $label.method2();
    $label.css('background-color', 'red');
});

Or even better with chaining:-

$('#button').click(function() {
    $("#label").method().method2().css("background-color", "red"); 
});

I found this the enlightening moment when I realized how the call stacks work.

Edit: incorporated suggestions in comments.

Answer

Understand how to use context. Normally, a jQuery selector will search the whole doc:

// This will search whole doc for elements with class myClass
$('.myClass');

But you can speed things up by searching within a context:

var ct = $('#myContainer');
// This will search for elements with class myClass within the myContainer child elements
$('.myClass', ct);
Answer

Don't use bare class selectors, like this:

$('.button').click(function() { /* do something */ });

This will end up looking at every single element to see if it has a class of "button".

Instead, you can help it out, like:

$('span.button').click(function() { /* do something */ });
$('#userform .button').click(function() { /* do something */ });

I learned this last year from Rebecca Murphy's blog

Update - This answer was given over 2 years ago and is not correct for the current version of jQuery. One of the comments includes a test to prove this. There is also an updated version of the test that includes the version of jQuery at the time of this answer.

Answer

Try to split out anonymous functions so you can reuse them.

//Avoid
$('#div').click( function(){
   //do something
});

//Do do
function divClickFn (){
   //do something    
}

$('#div').click( divClickFn );
Answer
  • Avoid abusing document ready.
  • Keep the document ready for initialize code only.
  • Always extract functions outside of the doc ready so they can be reused.

I have seen hundreds of lines of code inside the doc ready statement. Ugly, unreadable and impossible to maintain.

Answer

While using $.ajax function for Ajax requests to server, you should avoid using the complete event to process response data. It will fire whether the request was successful or not.

Rather than complete, use success.

See Ajax Events in the docs.

Answer

"Chaining" Animation-events with Callbacks.

Suppose you wanted to animate a paragraph vanishing upon clicking it. You also wanted to remove the element from the DOM afterwards. You may think you can simply chain the methods:

$("p").click(function(e) {
  $(this).fadeOut("slow").remove();
});

In this example, .remove() will be called before .fadeOut() has completed, destroying your gradual-fading effect, and simply making the element vanish instantly. Instead, when you want to fire a command only upon finishing the previous, use the callback's:

$("p").click(function(e){
  $(this).fadeOut("slow", function(){
    $(this).remove();
  });
});

The second parameter of .fadeOut() is an anonymous function that will run once the .fadeOut() animation has completed. This makes for a gradual fading, and a subsequent removal of the element.

Answer

If you bind() the same event multiple times it will fire multiple times . I usually always go unbind('click').bind('click') just to be safe

Answer

Pitfall: Using loops instead of selectors.

If you find yourself reaching for the jQuery '.each' method to iterate over DOM elements, ask yourself if can use a selector to get the elements instead.

More information on jQuery selectors:
http://docs.jquery.com/Selectors

Pitfall: NOT using a tool like Firebug

Firebug was practically made for this kind of debugging. If you're going to be mucking about in the DOM with Javascript, you need a good tool like Firebug to give you visibility.

More information on Firebug: http://getfirebug.com/

Other great ideas are in this episode of the Polymorphic Podcast: (jQuery Secrets with Dave Ward) http://polymorphicpodcast.com/shows/jquery/

Answer

Misunderstanding of using this identifier in the right context. For instance:

$( "#first_element").click( function( event)
{
   $(this).method( ); //referring to first_element
   $(".listOfElements").each( function()
   {
      $(this).someMethod( ); // here 'this' is not referring first_element anymore.
   })
});

And here one of the samples how you can solve it:

$( "#first_element").click( function( event)
{
   $(this).method( ); //referring to first_element
   var $that = this;
   $(".listOfElements").each( function()
   {
      $that.someMethod( ); // here 'that' is referring to first_element still.
   })
});
Answer

Avoid searching through the entire DOM several times. This is something that really can delay your script.

Bad:

$(".aclass").this();
$(".aclass").that();
...

Good:

$(".aclass").this().that();

Bad:

$("#form .text").this();
$("#form .int").that();
$("#form .choice").method();

Good:

$("#form")
    .find(".text").this().end()
    .find(".int").that().end()
    .find(".choice").method();
Answer

Always cache $(this) to a meaningful variable especially in a .each()

Like this

$(selector).each(function () {
    var eachOf_X_loop = $(this); 
})
Answer

Similar to what Repo Man said, but not quite.

When developing ASP.NET winforms, I often do

$('<%= Label1.ClientID %>');

forgetting the # sign. The correct form is

$('#<%= Label1.ClientID %>');
Answer

Events

$("selector").html($("another-selector").html());

doesn't clone any of the events - you have to rebind them all.

As per JP's comment - clone() does rebind the events if you pass true.

Answer

Avoid multiple creation of the same jQuery objects

//Avoid
function someFunc(){
   $(this).fadeIn();
   $(this).fadeIn();
}

//Cache the obj
function someFunc(){
   var $this = $(this).fadeIn();
   $this.fadeIn();
}
Answer

I say this for JavaScript as well, but jQuery, JavaScript should NEVER replace CSS.

Also, make sure the site is usable for someone with JavaScript turned off (not as relevant today as back in the day, but always nice to have a fully usable site).

Answer

Making too many DOM manipulations. While the .html(), .append(), .prepend(), etc. methods are great, due to the way browsers render and re-render pages, using them too often will cause slowdowns. It's often better to create the html as a string, and to include it into the DOM once, rather than changing the DOM multiple times.

Instead of:

var $parent = $('#parent');
var iterations = 10;

for (var i = 0; i < iterations; i++){
    var $div = $('<div class="foo-' + i + '" />');
    $parent.append($div);
}

Try this:

var $parent = $('#parent');
var iterations = 10;
var html = '';

for (var i = 0; i < iterations; i++){
    html += '<div class="foo-' + i + '"></div>';
}

$parent.append(html);

Or even this ($wrapper is a newly created element that hasn't been injected to the DOM yet. Appending nodes to this wrapper div does not cause slowdowns, and at the end we append $wrapper to $parent, using only one DOM manipulation):

var $parent = $('#parent');
var $wrapper = $('<div class="wrapper" />');
var iterations = 10;

for (var i = 0; i < iterations; i++){
    var $div = $('<div class="foo-' + i + '" />');
    $wrapper.append($div);
}

$parent.append($wrapper);
Answer

Using ClientID to get the "real" id of the control in ASP.NET projects.

jQuery('#<%=myLabel.ClientID%>');

Also, if you are using jQuery inside SharePoint you must call jQuery.noConflict().

Answer

Passing IDs instead of jQuery objects to functions:

myFunc = function(id) { // wrong!
    var selector = $("#" + id);
    selector.doStuff();
}

myFunc("someId");

Passing a wrapped set is far more flexible:

myFunc = function(elements) {
    elements.doStuff();
}

myFunc($("#someId")); // or myFunc($(".someClass")); etc.
Answer

Excessive use of chaining.

See this:

this.buttonNext[n ? 'bind' : 'unbind'](this.options.buttonNextEvent, this.funcNext)[n ? 'removeClass' : 'addClass'](this.className('jcarousel-next-disabled')).attr('disabled', n ? false : true);

Explanation

Answer

Use strings accumulator-style

Using + operator a new string is created in memory and the concatenated value is assigned to it. Only after this the result is assigned to a variable. To avoid the intermediate variable for concatenation result, you can directly assign the result using += operator. Slow:

a += 'x' + 'y';

Faster:

a += 'x';
a += 'y';

Primitive operations can be faster than function calls

Consider using alternative primitive operation over function calls in performance critical loops and functions. Slow:

var min = Math.min(a, b);
arr.push(val);

Faster:

var min = a < b ? a : b;
arr[arr.length] = val;

Read More at JavaScript Performance Best Practices

Answer

If you want users to see html entities in their browser, use 'html' instead of 'text' to inject a Unicode string, like:

$('p').html("Your Unicode string")
Answer

my two cents)

Usually, working with jquery means you don't have to worry about DOM elements actual all the time. You can write something like this - $('div.mine').addClass('someClass').bind('click', function(){alert('lalala')}) - and this code will execute without throwing any errors.

In some cases this is useful, in some cases - not at all, but it is a fact that jquery tends to be, well, empty-matches-friendly. Yet, replaceWith will throw an error if one tries to use it with an element which doesn't belong to the document. I find it rather counter-intuitive.

Another pitfall is, in my opinion, the order of nodes returned by prevAll() method - $('<div><span class="A"/><span class="B"/><span class="C"/><span class="D"/></div>').find('span:last-child').prevAll(). Not a big deal, actually, but we should keep in mind this fact.

Answer

If you plan to Ajax in lots of data, like say, 1500 rows of a table with 20 columns, then don't even think of using jQuery to insert that data into your HTML. Use plain JavaScript. jQuery will be too slow on slower machines.

Also, half the time jQuery will do things that will cause it to be slower, like trying to parse script tags in the incoming HTML, and deal with browser quirks. If you want fast insertion speed, stick with plain JavaScript.

Answer

Using jQuery in a small project that can be completed with just a couple of lines of ordinary JavaScript.

Answer

Not understanding event binding. JavaScript and jQuery work differently.

By popular demand, an example:

In jQuery:

$("#someLink").click(function(){//do something});

Without jQuery:

<a id="someLink" href="page.html" onClick="SomeClickFunction(this)">Link</a>
<script type="text/javascript">
SomeClickFunction(item){
    //do something
}
</script>

Basically the hooks required for JavaScript are no longer necessary. I.e. use inline markup (onClick, etc) because you can simply use the ID's and classes that a developer would normally leverage for CSS purposes.

Answer

Don't abuse plug-ins.

Most of the times you'll only need the library and maybe the user interface. If you keep it simple your code will be maintainable in the long run. Not all plug-ins are supported and maintained, actually most are not. If you can mimic the functionality using core elements I strongly recommend it.

Plug-ins are easy to insert in your code, save you some time, but when you'll need an extra something, it is a bad idea to modify them, as you lose the possible updates. The time you save at the start you'll loose later on changing deprecated plug-ins.

Choose the plug-ins you use wisely. Apart from library and user interface, I constantly use $.cookie , $.form, $.validate and thickbox. For the rest I mostly develop my own plug-ins.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.