To get a job as a front end developer, we need to nail the coding interview.
In this article, we’ll look at some harder questions about DOM manipulation.
How to check if an element is a descendant of a parent element?
We can use the parentNode
property of a DOM element to check if an element is a child of another element.
For example, we write the following function check if a node is a parent of a child node:
const isDescendant = (parent, child) => {
while (child.parentNode) {
if (child.parentNode == parent)
return true;
else
child = child.parentNode;
}
return false;
}
In the isDescendant
function, we get the parent node of the child
with the parentNode
property until we reach the top level.
In each parent, we check if the parentNode
property references the same node as the parent
.
We return true
if that’s the case. Otherwise, we go top the grandparent, great-grandparent and all the way to the top level and return true
if we find that parentNode
is the same node as parent
.
Otherwise, we return false
if none of them are the same as parent
.
For example, if we have the following HTML:
<div>
<p>
<span></span>
</p>
</div>
<div id='foo'></div>
Then if we have the following code:
const div = document.querySelector('div');
const p = document.querySelector('p');
const span = document.querySelector('span');
const foo = document.querySelector('#foo');
console.log(isDescendant(div, p));
console.log(isDescendant(div, span));
console.log(isDescendant(foo, span));
The first 2 should log true
and the last one should false
since the first div is the parent of p and grandparent of the span.
The div with ID foo isn’t a parent of any of the other nodes.
What’s the difference between innerHTML and appendChild?
innerHTML
removes all current child nodes of the elements. Then the JavaScript interpreter parses the string and then assigns the parsed string to the element as the children.
appendChild
attaches the child node to the parent node it’s called on as the name suggests.
For example, if we have the following HTML:
<div>
<p>foo</p>
</div>
Then if we write:
const div = document.querySelector('div');
div.innerHTML = '<p>bar</p>';
Then we only see ‘bar’ on the screen since we set the innerHTML
property to overwrite what’s there.
On the other hand, if we use appendChild
as follows:
const div = document.querySelector('div');
const p = document.createElement("p");
const bar = document.createTextNode("bar");
p.appendChild(bar);
div.appendChild(p);
Then we add the p element with the text node ‘bar’ and the call appendChild
to append p
to the div
, we see:
foo
bar
displayed on the screen since we added a new child to the end of the list of child elements to the div.
What is createDocumentFragment and why you might use it?
document.createDocumentFragment
lets us create a new DocumentFragment
in which DOM nodes can be added to build an offscreen DOM tree.
For example, if we have the following HTML:
<ul></ul>
Then we can use createDocumentFragment
as follows to create an offscreen fragment and then insert the whole thing into the DOM:
const element = document.querySelector('ul');
const fragment = document.createDocumentFragment();
const fruits = ['apple', 'orange', 'grape'];
fruits.forEach((fruit) => {
const li = document.createElement('li');
li.textContent = fruit;
fragment.appendChild(li);
});
element.appendChild(fragment);
With createDocumentFragment
, we added all the nodes to fragment first and then append the whole thing to our ul
element with appendChild
.
DocumentFragment
is a lightweight or minimal part of a DOM or a DOM subtree. It’s useful for manipulating the part of the DOM multiple times.
DocumentFragments
are managed in memory so that the CPU won’t be taxed by expensive operations.
What is reflow? What causes reflow? How could we reduce reflow?
Reflow is the situation where we change the position of the elements according to screen size or position changes.
If we change the width of the screen, like when we’re rotating the phone’s screen, then everything has to be moved to display in the screen property.
Reflows are expensive since everything has to be moved, especially on smaller devices like phones.
Reflows are caused by changing layout, resizing the window, changing the dimension of any element, changing fonts in any way, moving DOM elements, adding or removing stylesheets, and anything else that make similar kinds of changes.
To avoid reflow, we avoid setting multiple inline styles, apply animations to elements that fixed or absolute position, and avoid using tables for layout.
Conclusion
We can use the parentNode
property of a node to get the parent of a node.
Setting the innerHTML
property of an element overwrites all the existing children and replace them with new ones from the string we set.
appendChild
attaches a new child element to the end of the subtree.
DocumentFragments
are lightweight offscreen elements that hold DOM elements. It’s managed in memory and can be added to the screen like any other element.
Reflow is the position change of elements according to some other changes on the screen. It’s an expensive operation that should be avoided.