You are correct in that jQuery doesn't re-query the DOM for elements on each call, but what it does do is re-loop through it's internal cached collection to apply these CSS rules. The perf hit isn't noticeable when jQuery's selection (internal collection) is small. Imagine a webpage with lots of elements you want to select and then want to interact with... that is what I am trying to bring attention to.
Is it re-looping? Doesn't the .css setter return a jQuery object that is used by the next method in the chain? So it's actually only going through an implicit loop of $( ".widget" ) once?
It's looping twice, because the first time you call to .css it loops through each element to add the first style, and then it loops through again on the second .css to add the second style. You could roughly replicate it with:
var i, elements = document.getElementsByClassName('widget');
for (i = 0; i < elements.length; i++) {
elements[i].style.color = "green";
}
for (i = 0; i < elements.length; i++) {
elements[i].style.fontSize = "16px";
}
Two loops. The "improved" suggestion would be roughly equivalent to:
var i, elements = document.getElementsByClassName('widget');
for (i = 0; i < elements.length; i++) {
elements[i].style.color = "green";
elements[i].style.fontSize = "16px";
}
This is one loop, but it's still O(n). If there are 100 ".widget" elements on the page, the first code does 200 writes to the style property. The second code does 200 writes to the style property. The difference in jumps and compares isn't worth thinking about when style changes are so expensive, the difference is probably immeasurable.
The second version is better just because it's cleaner code, but that's it.
I'm not convinced that there's two loops -- aren't the .css() methods chained together, and would be executed right after each other for each step through the implied loop?
In
$(".widget").css("color", "green").css("font-size", "16px");
does the color of all the widgets change, and then the fontSize, or does the color/fontSize change together for each widget?
I suspect the latter...
Chained functions call independently and completely before returning to the next. The css function [0] operates on the "array" this returned by $ using an anonymous function [1] at a call site in the access function [1] [2]; access then returns the object formerly known as this [3]. Chain, rinse, and repeat to your heart's content.
There must obviously be two loops, jQuery can't perform magic. The first .css() call will iterate over the cached array of elements, apply the color attributes and then return a reference to the jQuery instance. The second call will loop once again and this time apply the font-size attribute.
There is no extra DOM lookups, but there will certainly be two loops.