Thursday 14 October 2010

jQuery Object

Quite often when I get back to jQuery after some time without touching it, I get some confusion with the almighty jQuery object (well, I would say this is sample of the God Object antipattern).
When we use some of the selection methods to obtain DOM elements, we get an instance of the jQuery object containing the selected DOM elements (DOM elements, not jQuery wrappers, so we usually have to wrap them into a jQuery object again with $(this) for additional processing). This instance is similar to an Array, but it's not, it's an Array-like object.
It has a length property and the DOM elements are accessible through numeric indexes, so how is this?
Each DOM element to be contained by the instance of the jQuery object is added to this instance through an increasing numeric property, and a length property is also added and kept updated. Bear in mind that for these numeric properties we can only use the "[]" notation, not the "." notation. Yes, all this is one of those magical JavaScript things. What this means is that we can do this with an object:


var obj1 = {};

obj1.name = "xana";

obj1["age"] = 30;

obj1["0"] = "item1";

obj1.length = 1;

obj1[1] = "item2";
obj1.length = 2;


so we get an Array-like object, with a length of 2, 2 items accessible via numeric index and other 2 properties ("xana" and 30).
As it's not a real Array, there's some gotcha to take into account, for example, we should not iterate it with a for in loop if what we want is iterating its items collection. I mean, we can iterate (thought it's not much common) a true Array like this:

for (index in ar)
printf(ar[index]);


but used on our Array-like object, we would get a listing of all it's other properties and methods along with the indexed values.

Of course, the usual way to iterate our jQuery object is either with the .each jQuery instace method (not to be confused with the .each "static method")

var $aux = $("<ul><li>xose</li><li>xuan</li></ul>");
//jQuery object with an only item (ul)
var $peopleList = $aux.children("li");
//jQuery object with two items (li)
$peopleList.each(function()
{
printf($(this).text());
});


or with a normal for loop:

for(var i=0; i<$peopleList.length; i++)
printf($peopleList[i].innerHTML);


you can view/test the code here

No comments:

Post a Comment