Arshad Khan Arshad Khan - 1 month ago 13
HTML Question

Why use cloneNode when I can clone a node using querySelector?

Below two function does same thing - first they copy an element then clear the body and then add the element back. My question is which one is better and in what conditions cloneNode using function or the other one will not work ?

Using querySelector

function noahArc(animal) {
// Preserve the poor animal and its children
var arc = document.querySelector(animal);

// Flood the entire body with rage, water and thunder
document.body.innerHTML = "";

// Restore the preserved animal into the post-apocalyptic world
document.body.appendChild(arc);
}

noahArc('.asd');


Using cloneNode

function noahArc(animal) {
// Preserve the poor animal and its children
var arc = document.getElementsByClassName(animal)[0].cloneNode(true);

// Flood the entire body with rage, water and thunder
document.body.innerHTML = "";

// Restore the preserved animal into the post-apocalyptic world
document.body.appendChild(arc);
}

noahArc('asd');

Answer

First, for the avoidance of doubt: querySelector does not clone elements. It just gives you a reference to the element that already exists. In a non-buggy browser, that reference remains valid even if you wipe the conents of body after you get the reference. It just means the element isn't in the document anymore.

Second, your edit and various comments suggesting there's a difference in your code depending on whether you use querySelector or getElementsByClassName to select the element are incorrect. In the code shown, it makes no difference whatsoever. The only difference of consequence in your examples is whether you clone the node.

So, looking at the two examples:

Your first example will fail in some versions of IE because of a bug it has where it wipes the contents of the descendant element when you assign to the innerHTML of its ancestor even when you have a reference to the descendant element. It shouldn't fail, but it will. (This bug cost me hours of debugging time sometime last year...) I don't think Edge has this bug. I've just verified it's still an issue with IE11 using this test:

function noahArc(animal) {
  var arc = document.querySelector(animal);
  document.body.innerHTML = "";
  document.body.appendChild(arc);
}

noahArc('.asd');
console.log("Done, you should still see 'this is the div' above, but you won't in IE");
<div class="asd">this is the div</div>

Other than that, neither is "better." It depends on what you want to do.

Your first example attempts to keep the same element in the document (which may have event handlers attached to it). It doesn't make a copy, and only works (on browsers where it works) because the original is removed from the document by assigning to its ancestor's innerHTML.

Your second example creates a copy of the element (which won't have event handlers on it).

Which you use depends on what you want to achieve, and what browsers you want to support.