Wilt
Wilt

Reputation: 44422

How do jQuery convenience methods end up in my DOM elements?

I am just curious to know how this works.
When using jQuery my DOM elements come with all kinds of convenience methods.
As an example I just take the css method:

Get the value of a computed style property for the first element in the set of matched elements or set one or more CSS properties for every matched element.

Example (also here in this Fiddle)

HTML code:

<div id="test" style="background-color:#ff0000;">
   MY RED DIV
</div>

Javascript code:

var color = $('#test').css("background-color");
console.log(color);

This outputs:

rgb(255, 0, 0)

Does jQuery extend all my DOM element objects with such convenience methods? Or are all my elements wrapped in Proxy classes? Or how does this work?

How do all these extra methods influence the performance of my application or document object model?

Upvotes: 1

Views: 65

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1075457

How do jQuery convenience methods end up in my DOM elements?

They don't. They're in jQuery objects (specifically, the prototype of those jQuery objects), which are wrappers around sets of DOM elements. The actual DOM elements aren't extended (there was a lib that did that, called PrototypeJS, but it's not how jQuery works).

With your div, when you do this:

var test = $('#test');

...test refers to a jQuery object, which has one DOM element inside it, like this:

        +−−−−−−−−−−−−−−−+
test−−−>| jQuery object |
        +−−−−−−−−−−−−−−−+     +−−−−−−−−−−−−−−−−+
        | 0             |−−−−>| HTMLDivElement |
        | length: 1     |     +−−−−−−−−−−−−−−−−+
        +−−−−−−−−−−−−−−−+     | id: "test"     |
                              | ...            |
                              +−−−−−−−−−−−−−−−−+

As you can see, jQuery objects are array-like: They have a length property, and properties for each of their elements in numeric order starting with 0.

Similarly, if we had

<div class="foo" id="one"></div>
<div class="foo" id="two"></div>
<div class="foo" id="three"></div>

and did

var test = $(".foo");

we'd have:

        +−−−−−−−−−−−−−−−+
test−−−>| jQuery object |
        +−−−−−−−−−−−−−−−+       +−−−−−−−−−−−−−−−−−−+
        | 0             |−−−−−−>|  HTMLDivElement  |
        | 1             |−−−+   +−−−−−−−−−−−−−−−−−−+
        | 2             |−+ |   | id: "one"        |
        | length: 3     | | |   | className: "foo" |
        +−−−−−−−−−−−−−−−+ | |   | ...              |
                          | |   +−−−−−−−−−−−−−−−−−−+
                          | | 
                          | |   +−−−−−−−−−−−−−−−−−−+
                          | +−−>|  HTMLDivElement  |
                          |     +−−−−−−−−−−−−−−−−−−+
                          |     | id: "two"        |
                          |     | className: "foo" |
                          |     | ...              |
                          |     +−−−−−−−−−−−−−−−−−−+
                          |   
                          |     +−−−−−−−−−−−−−−−−−−+
                          +−−−−>|  HTMLDivElement  |
                                +−−−−−−−−−−−−−−−−−−+
                                | id: "three"      |
                                | className: "foo" |
                                | ...              |
                                +−−−−−−−−−−−−−−−−−−+

They're kept in the jQuery object in document order, which is why we see them in the listed order above.

This set-based nature of jQuery is a big part of its strength compared to the afore-mentioned PrototypeJS or the DOM itself. Want to turn all elements matching a selector green? With jQuery it's:

$("selector").css("color", "green");

With the DOM, it's a for loop:

var elements = document.querySelectorAll("selector");
for (var i = 0; i < elements.length; ++i) {
    elements[i].style.color = "green";
}

...or a helper function. On very modern browsers, we can get more concise without non-standard helpers:

Array.from(document.querySelectorAll("selector")).forEach(e => e.style.color = "green");

...but succinct it's not. :-)

Oddly, the set-based nature of jQuery doesn't come through to its getter methods. For instance, the code above sets the color green on all elements in the jQuery set, but this code:

console.log($("selector").css("color"));

...only gets the color from the first element in the set. Almost all of jQuery's getter methods are like that (the odd one out being text, for some reason). But the alternative, of course, was to return an array of all of those colors, and John Resig (the original author) decided to go with an assymmetric API instead.

Upvotes: 1

Related Questions