Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How JQuery objects assigned to a variable detect changes?

(First of all sorry for my English) I can understand assigning JQuery objects that found by JQuery selectors, to a variable has better performance then using JQuery Selectors every time. The part that i cannot understand is how JQuery detects changes that are not manipulated by JQuery? Here is an example:

<div id="divState">First State</div>

$(document).ready(function () {
     var testElement = $("#divState");
     alert(testElement.text());//alerts "First State".
     document.getElementById("divState").innerHTML = "Second State";//Div has changed outside of the JQuery object.
     alert(testElement.text());//alerts "Second State"??? How a variable detects changes.
});
like image 754
camadan Avatar asked Feb 11 '23 00:02

camadan


1 Answers

Well, it knows, but it doesn't know . . .

As Blazemonger points out, when you create a jQuery object, one of the items in the object is, essentially, just a pointer to the actual DOM element in the page. So, like you show in your example, any time you inspect the properties of that object, it will inspect the element and show you whatever they currently are. If they change in between checks, you will see the difference.

However, jQuery is not 100% smart . . . if you were to change something fundemental to the selector, it is not smart enough to know to update the collection of objects, without re-selecting them. For example, look at this HTML:

<div id="container">
    <div class="similarDivs">Div 1</div>
    <div class="similarDivs">Div 2</div>
    <div class="similarDivs">Div 3</div>
</div>

If you run the following code against it:

var $mainGroup = $("#container");
var $subGroup = $mainGroup.find(".similarDivs");
console.log($subGroup);

. . . your console would show: Object[div.similarDivs, div.similarDivs, div.similarDivs]

But, if you were to follow that up with this code:

$mainGroup.children(":eq(0)").removeClass("similarDivs");
console.log($subGroup);

. . . your console would show: Object[div, div.similarDivs, div.similarDivs]

It is smart enough to see that the 1st div is no longer tagged with the "similarDivs" class, but it is not smart enough to know that, technically, that means that it should no longer be part of the $subGroup selection group. Again, this is because the selector created a bunch of jQuery objects that point to all of the DOM elements that matched the selection criteria, at a single point in time.

The only way that you could get $subGroup to reflect the change in its collection is by re-running the selector:

$subGroup = $mainGroup.find(".similarDivs");
console.log($subGroup);

. . . resulting in: Object[div.similarDivs, div.similarDivs]


One of the biggest reasons that this is so important (apart from knowing that when you use selectors :) ), is because Javascript does NOT behave that way . . . if you were to write a similar set of functionality in JS, you would get different results:

var mainGroup = document.getElementById("container");
var subGroup = mainGroup.getElementsByClassName("similarDivs");
console.log(subGroup);
mainGroup.children[1].className = "";
console.log(subGroup);

That code would give you:

HTMLCollection[div.25dd58, div.25dd58, div.25dd58]
HTMLCollection[div.25dd58, div.25dd58]

. . . without needing to "re-select" the elements (note: it is also returning an HTMLCollection, not a jQuery Object, which clues you in to the difference in behavior).

like image 55
talemyn Avatar answered Feb 12 '23 13:02

talemyn