Hacker News new | past | comments | ask | show | jobs | submit login

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.



What's your definition of a non-small jQuery selection? That sample test loops over 272 elements with no discernible performance effect.


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.

[0] https://github.com/jquery/jquery/blob/master/src/css.js#L102

[1] https://github.com/jquery/jquery/blob/master/src/css.js#L103

[2] https://github.com/jquery/jquery/blob/master/src/core.js#L75...

[3] https://github.com/jquery/jquery/blob/master/src/core.js#L75...


Doh -- of course... Many thanks for the explanation & the links!


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.


You can walk through what the .css function call is doing here:

http://sherlockcode.com/demos/jquery/#!/src/css.js:102

Ctrl+Click on the jQuery.access call on the next line to jump to its definition.


Also, I'd imagine you could get hit with lots of UI repaints that could be minimized if you iterated over the loop manually.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: