7

The reason I ask is because I'm thinking of storing a bunch of DOM nodes in this huge and multi-dimensional array I have.

Cost: takes up space in memory. The question is how much space, and that depends on whether I'm getting references or actual DOM nodes.

Benefits: 1) It'll make my code a lot simpler. 2) I could avoid traversing and instead just reference the DOM node from my array.

Thoughts?

Adam Zerner
  • 17,797
  • 15
  • 90
  • 156
  • 2
    The difference you make between *actual DOM nodes* and *references* is quite ambiguous. DOM nodes are never returned "by value" (which would mean copies separate from the original nodes, with changes made to the copies not being reflected in the originals), always "by reference". The `clone()` method allows you to make a copy of a node, but a reference to that copy is still returned. – Frédéric Hamidi Jul 20 '15 at 14:41
  • @FrédéricHamidi that's interesting. Would you mind elaborating? What are the implications as far as how much space these references take up in memory? – Adam Zerner Jul 20 '15 at 14:42
  • 1
    @Adam, typically these references are the size of a pointer (but that's still platform and implementation-dependent). The complete state of the nodes is not cloned. – Frédéric Hamidi Jul 20 '15 at 14:44
  • @FrédéricHamidi well that answers my question then. Would you mind/like to write up an answer? If not I will. Also, do you know how big the jQuery object is compared to the reference to the DOM node? Storing the jQuery object would be more convenient, but the downside is that it's bigger. – Adam Zerner Jul 20 '15 at 14:46
  • 1
    @Adam, it's hard to reliably tell how "big" a jQuery object is because these objects maintain a stack of previously matched elements (so `end()` can work). Therefore, the actual size of a given jQuery object depends on the number of chained calls you have made on it, among other things. – Frédéric Hamidi Jul 20 '15 at 14:58

6 Answers6

0

This answer is wrong, please see the comments below.


Document.getElementById() and methods or wrappers that rely on it return a reference.
Likewise for Document.querySelector().

This all stems from the DOM4 spec, which states that (emphasis mine):

A collection is an object that represents a lists of DOM nodes. A collection can be either live or static. Unless otherwise stated, a collection must be live.

From a programming point of view this notion is easy to understand, you waste less memory and no time is spent copying things around, leading to faster execution.

However, for Document.querySelectorAll() we have an interesting case:

The NodeList object returned by the querySelectorAll() method must be static.

This means, as MDN puts it, that Document.querySelectorAll()

Returns a non-live NodeList of all the matching element nodes.

This means that the returned set is not a set of references to the original nodes, but instead to a set of nodes that represent the nodes at the time the query was executed. This means that a copy of all the matching nodes had to be made and you're no longer working with references to the live nodes.

Etheryte
  • 24,589
  • 11
  • 71
  • 116
  • How do you know that similar methods and wrappers do the same? I don't see anything about [Document.querySelector()](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector) returning a reference. – Adam Zerner Jul 20 '15 at 14:31
  • What does live/static mean? – Adam Zerner Jul 20 '15 at 15:02
  • 1
    @Nit, ah, I get where the misunderstanding is. "Static" and "live" lists are not what you think they are: both contain *references* to the nodes, but a "live" list will transparently "add" or "remove" nodes when they start or stop matching the criteria that makes them members of the list (e.g. `childNodes` will automagically contain children that were added later). "Static" lists do not add or remove nodes even if they start or stop matching that criteria further on. – Frédéric Hamidi Jul 20 '15 at 15:02
  • @AdamZerner Quoting from the spec, _"If a collection is live, then the attributes and methods on that object must operate on the actual underlying data, not a snapshot of the data."_ – Etheryte Jul 20 '15 at 15:03
  • @Nit, in other words, the spec would be clearer if it said "If a collection is live, then the attributes and methods on that *collection* must operate on the actual underlying data, not a snapshot of the data". – Frédéric Hamidi Jul 20 '15 at 15:06
  • @FrédéricHamidi Thanks for your input, I'm not sure the idea is still clear to me though, could you write up a detailed answer? – Etheryte Jul 20 '15 at 15:09
  • 1
    @Nit, not right now I'm afraid (and the subject at hand is very broad). Still, I found [an existing question that elaborates on the differences between static and live collections](http://stackoverflow.com/q/28163033/464709). – Frédéric Hamidi Jul 20 '15 at 15:17
0

From jQuery site:

… jQuery() — which can also be written as $() — searches through the DOM for any elements that match the provided selector and creates a new jQuery object that references these elements

jQuery Documentation

0

jQuery returns the actual DOM Node. It's why you will find yourself writing $(this) most of the time. This is because you want to wrap your node in jQuery to be able to use some jQuery methods. However, it's recommended (almost in the guidelines) to cache your DOM nodes through references. For example,

var div = $('div');
div.dosomeMethod();
div.append();

This ensures that you are not traversing the entire DOM tree (the expensive DOM part) whenever you're trying to access some element. Whenever you do updates, ensure you're doing them as a batch.

Bwaxxlo
  • 1,860
  • 13
  • 18
0

in this example I show how to clone existing DOM element to object in memory, also create object in memory without pushing it to body, created collection objects, appended elements from collection to body and keep referenced objects, removed from body. and so many operations...

var $newElement1 = $(selector).clone(); // create new element from existing and store in memory
var $newElement2 = $('<div>blabla</div>'); // create new element from html code and store in memory

var elements = [];
elements.push($newElement1);
elements.push($newElement2);

for(var i in elements) {
  elements[i].appendTo($('body'));
}

$newElement1.remove(); // will remove it from body

** but I recommend You to use frameworks like: angularjs, reactjs, emberjs to save Your time

num8er
  • 18,604
  • 3
  • 43
  • 57
0

A reference to the object is returned. See here: https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById

0

In short:

  • Some JavaScript methods return references to the DOM Node.
  • Some JavaScript methods return array-like objects that contain references to the DOM Nodes. These objects aren't very big(?).
  • jQuery returns a jQuery object that contains references to the DOM Node(s). These jQuery objects could get quite big, depending on how many chained calls are made.
  • The actual DOM nodes are never actually returned "by value".
  • The size of the references themselves are small. Typically the size of a pointer.

JavaScript:

HTMLCollection and NodeList contain references to DOM nodes. They don't seem to be very big objects.

enter image description here enter image description here


Live vs. Non-Live

From MDN:

In some cases, the NodeList is a live collection, which means that changes in the DOM are reflected in the collection. For example, Node.childNodes is live:

 var parent = document.getElementById('parent');
 var child_nodes = parent.childNodes;
 console.log(child_nodes.length); // let's assume "2"
 parent.appendChild(document.createElement('div'));
 console.log(child_nodes.length); // should output "3"

In other cases, the NodeList is a static collection, meaning any subsequent change in the DOM does not affect the content of the collection. document.querySelectorAll returns a static NodeList.

enter image description here


jQuery

From learn.jquery.com

A jQuery object is an array-like wrapper around one or more DOM elements. To get a reference to the actual DOM elements (instead of the jQuery object), you have two options. The first (and fastest) method is to use array notation:

$( "#foo" )[ 0 ]; // Equivalent to document.getElementById( "foo" )

The second method is to use the .get() function:

$( "#foo" ).get( 0 ); // Identical to above, only slower.

You can also call .get() without any arguments to retrieve a true array of DOM elements.

Community
  • 1
  • 1
Adam Zerner
  • 17,797
  • 15
  • 90
  • 156