
JQuery implicit loops - davej
http://www.elijahmanor.com/2013/01/yo-dawg-i-herd-you-like-loops-so-jquery.html?utm_source=javascriptweekly&utm_medium=email
======
duopixel
These two pieces of code should have around the same performance:

    
    
        $( ".widget" ).css( "color", "green" ).css( "font-size", "16px" );
    
        $( ".widget" ).css({ 
          "color": "green",
          "font-size": "16px"
        })
    

Fact is, jQuery also has to loop through the object and assign each css style
declaration, so the performance is very similar.

<http://jsperf.com/chained-css-declarations-jquery>

~~~
HyprMusic
In all my days of bitching about people chaining like this, never once did it
occur to me they have the same big O notation performance.

I still prefer the latter style though, in my opinion it's far easier to read.

~~~
pessimism
I’ve always questioned the sanity of the people who do something similar to
the former example in d3.js; this is so much easier:
<http://pygm.us/IhBQwUAI>.

------
m0th87
The performance implications section is completely wrong. jQuery doesn't re-
query for elements on each call; the results are cached. Here's a test:
<http://jsperf.com/jquery-s-css-object-vs-multiple-calls>

My results (Chrome, Mac) are showing they have the same performance. On
smaller HTML pages, multiple calls to css() actually outperformed the single
call significantly (~30%).

~~~
elijahmanor
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.

~~~
pixl8ed
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?

~~~
evan_
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.

~~~
pixl8ed
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...

~~~
thezilch
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...](https://github.com/jquery/jquery/blob/master/src/core.js#L750)

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

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

------
jccc
There is another explanation than the one given for seeing examples like this
in someone else's code:

    
    
      // Indications of Confusion
      $( ".widget" ).each( function() {
        $( this ).css( "color", "green" );
      });
    

I think this is at least as likely to be the remains of a block of code that
was pared down and not (yet) re-implemented differently. The developer might
have intended to return with replacement code and never did, perhaps this is
an ongoing project on which you're a collaborator, perhaps the developer just
forgot about it. It may still be bad code, but concluding wherever you find it
that the reason is fundamental ignorance seems hasty.

It will always be a struggle for me to resist the bias against Other People's
Code that causes me to underestimate the developer whenever I encounter
something wrong. Maybe it's a minor point, but I think this bias exists in
everyone and that this is an example of it.

