Thursday, January 12, 2012

Nested Statements in jQuery

As we all know, jQuery's powerful selectors allow you to quickly create an object that contains multiple elements from the DOM, and manipulate all of them in a single line. (Noob stuff, I know, but hang with me, here...) For example:

$("div").html(generateSomethingRandom());

We're saying, "Find all the divs, and generate something random to go inside them." Obviously, the content will only get inserted if one or more divs are on the page.

If you were to write that instruction without jQuery, you'd probably write it a little something like this:

// Translation of $("div").html(generateSomethingRandom());
 
var divs = findDivs(); // a fictitious method
for(var i = 0; i < divs.length; i++) {
 div.innerHTML = generateSomethingRandom();
}
But, in fact, that would be incorrect! In the jQuery version of the code, generateSomethingRandom() will be called once. Always.
  • If there is one div, it'll be called once.
  • If there are two divs, it'll be called once.
  • And, quite significantly, if there are no divs, it'll be called once.
A more accurate translation of the statement would look something like this:
// More accurate translation of $("div").html(generateSomethingRandom());
 
var divs = findDivs();
var somethingRandom = generateSomethingRandom();
for(var i = 0; i < divs.length; i++) {
 div.innerHTML = somethingRandom;
}

So, why is this important?

First, you could end up with some performance issues if you're doing anything significant inside that method. For example, if you're using a JavaScript templating engine to render the HTML -- you could be slowing down your app rendering HTML that's never actually even used.

Second, if you're expecting the method to be called once for each element, you'd be disappointed. In our case, we might have expected a different random string to show in each div, but all three get the same string.

Here's a full example:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Example</title>
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

<style type="text/css">
div {
 border: 1px solid red;
}
</style>

<script>
 function generateSomethingRandom() {
  var result = "";
  for(var i = 0; i < 10; i++) {
   var asciiCode = Math.floor(Math.random()*15) + 62;
   result += String.fromCharCode(asciiCode);
  }
  return result;
 }
  
 $(document).ready(function() {
  $("#magicButton").click(function() {
   $("div").html(generateSomethingRandom());
  });
 });
</script>
 
</head>
 
<body>

<div>Hit</div>
<div>the</div>
<div>Bits</div>
 
<input type="button" id="magicButton" value="Click me, if you please." />
 
</body>
</html>

No comments:

Post a Comment

Profile Picture
Dave Leeds
My Hobbies:
  • Programming
  • Cartooning
  • Music Writing
Full Profile