Wednesday, January 25, 2012

Find the jQuery Bug #2: Point of No Return

Introduction


In this open-ended series I'll be showcasing a snippet of buggy jQuery code that you might encounter, explain what the problem is, and then identify how you can easily resolve the issue.

You can view my other post in this series...

The Desired Feature


We want to take the following HTML unordered list and build a JavaScript function that will determine if a specific value is present.


The Buggy Code


The following code snippets is our first attempt at solving the problem, but there is a subtle error. Do you see it?


You can view, run, and edit the above code sample from JSBin.

The results that we expected were false, true, true, true, false, but instead the output in the console is false, false, false, false, false.

The Underlying Problem


At the root of the problem is the special jQuery .each() method we are using. The .each() method is a very handy way to iterate over the jQuery collection, however there is a special meaning to return false within a .each() method.

"We can stop the loop from within the callback function by returning false." --http://api.jquery.com/each

Upon further examination of the code it even makes further sense why it wouldn't work. Most of us are familiar that a return statement exists the current function, but in this case we aren't invoking the function... jQuery is! So, jQuery has control over what happens when you exit your function prematurely and it recognizes return false to mean something special.

A Solution


The solution to fix this problem is really simple and straightforward. All you really need to do is to introduce another variable hasNumber. If the number was found, then set the hasNumber variable to true and then return false; to exit the .each() method.


You can view, run, and edit the above code sample from JSBin.

If you test out the code again below you'll notice that now that we are getting the expected output of false, true, true, true, false.

An Alternate Solution


An alternate way to solve this problem would be to use another technique completely. In the following example we will use the jQuery.grep method. The jQuery.grep method is defined as the following:

"Finds the elements of an array which satisfy a filter function. The original array is not affected." --http://api.jquery.com/jquery.grep/


You can view, run, and edit the above code sample from JSBin.

Although the code looks shorter, it is less performant than the previous solution. Can you tell why? The code is not exiting once the number has been found, but instead goes through each array item and executes the callback function. We get the correct answer, but for a price.

Conclusion


The key concept to remember here is to be aware of the special mean of return false; inside of a jQuery .each() method to exit the loop. Even if you have never made this mistake before, maybe it has opened up your eyes to the fact you can exit out of a .each() method!

Until next time...

No comments:

Post a Comment