JavaScript vs jQuery HTML Collections

Craig Buckler
Share

HTMLCollection objects are returned from document.getElementsByTagName, document.getElementsByName and document.getElementsByClassName methods (not supported in all browsers). Superficially, they’re similar to arrays since they have length property and elements can be accessed by [index]. However, they’re not arrays; methods such as push(), slice() and sort() are not supported.

Consider the following HTML document:


<body>
	<p>Paragraph 1</p>
	<p>Paragraph 2</p>
	<p>Paragraph 3</p>
</body>

Let’s grab every paragraph node using getElementsByTagName and a jQuery selector:


var pCollection = document.getElementsByTagName("p");
var pQuery = $("p");

console.log("pCollection.length: ", pCollection.length);
console.log("pQuery.length: ", pQuery.length);

Both return the same nodes so the collection length is 3:


pCollection.length: 3
pQuery.length: 3

We’ll now add another paragraph element to the document and look at the collections again:


// add new paragraph
var newp = document.createElement("p");
newp.appendChild(document.createTextNode("Paragraph 4"));
document.body.appendChild(newp);
// 
// display length
console.log("pCollection.length: ", pCollection.length);
console.log("pQuery.length: ", pQuery.length);

The result:


pCollection.length: 4
pQuery.length: 3

HTMLCollection objects are live. They are automatically updated whenever the underlying document changes. jQuery and most other JavaScript libraries use methods such as document.getElementsByTagName() but copy the resulting nodes to a real array. Therefore, it’s a query on the state of the document at that time: it is never updated.

There are advantages and disadvantages with both methods. For example, the following code causes an infinite loop since the HTMLCollection length increases as <p> elements are added:


var pCollection = document.getElementsByTagName("p");
for (var i = 0; i < pCollection.length; i++) {
	document.body.appendChild(pCollection[i].cloneNode(true));
}

That said, there may be situations when a faster, native live HTMLCollection is more useful than a static collection of jQuery nodes or repeatedly making the same selection. Fortunately, we can pass any collection to jQuery when we want to manipulate it, e.g.


var pCollection = document.getElementsByTagName("p");
// ... add nodes, do work, etc ...
$(pCollection).addClass("myclass");

jQuery and other libraries can cut development effort but always check whether it’s possible to write more efficient code in plain old JavaScript without incurring additional file requests and processing overheads.