A JavaScript Interview Question

24 Apr, 2013
23 Dec, 2012

Here is an interesting javascript interview question. While it seems to be trivial at first glance, there’s actually some fundamental concepts that one must know in order to truly appreciate and answer this question.

The Question

Alter the following javascript snippet to make it more efficient.

Now, before jumping to the answer, lets look at the code above and try and understand what it does. Within the for loop this snippet creates a HTML “div” element and appends the text “Node <number>” (where number ranges from 1 to 1000) and appends it to the DOM.

So what’s inefficient about this code? Well to understand this, lets look at two fundamental DOM manipulation concepts “Repaint” and “Reflow”.

  • Repaint:

    Repaint – also known as redraw – is what happens whenever something is made visible when it was not previously visible, or vice versa, without altering the layout of the document. An example would be when adding an outline to an element, changing the background color, or changing the visibility style. Repaint is expensive in terms of performance, as it requires the engine to search through all elements to determine what is visible, and what should be displayed.

  • Reflow:

    A reflow is a more significant change. This will happen whenever the DOM tree is manipulated, whenever a style is changed that affects the layout, whenever the className property of an element is changed, or whenever the browser window size is changed. The engine must then reflow the relevant element to work out where the various parts of it should now be displayed. Its children will also be reflowed to take the new layout of their parent into account. Elements that appear after the element in the DOM will also be reflowed to calculate their new layout, as they may have been moved by the initial reflows. Ancestor elements will also reflow, to account for the changes in size of their children. Finally, everything is repainted.

Reflows are very expensive in terms of performance, and is one of the main causes of slow DOM scripts, especially on devices with low processing power, such as phones. In many cases, they are equivalent to laying out the entire page again.

Back to the problem

DOM access and manipulation are the most common tasks in browser javascript. And naturally, they are also the most common bottleneck when it comes to javascript performance. Generally speaking, DOM access and manipulation are expensive, because DOM is not a part of javascript engine. It is separated and doesn’t belong to ‘core javascript’. For browsers, it makes sense because a javascript application probably doesn’t need and DOM at all while other languages may need to work with the DOM.

In the above, we need to modify the DOM tree. Document tree modification will trigger reflow. Adding new elements to the DOM, changing the value of text nodes, or changing various attributes will all be enough to cause a reflow. Making several changes one after the other, may trigger more than one reflow, so in general, it is best to make multiple changes in a non-displayed DOM tree fragment. The changes can then be made to the live document’s DOM in one single operation.

A simple solution

Let’s look at a simple solution to this problem in the code below.

In the above code, we create a document fragment which is not part of the live DOM tree and add elements to it within the loop. Once our desired DOM tree fragment is ready, we append it to the live DOM tree which results in only one reflow instead of 1000 reflows in the origin snippet.

There are other ways to solve this problem. To learn more ways to manipulate the DOM tree with minimum reflows, please refer to the Efficient Javascript article by Mark ‘Tarquin’ Wilton-Jones.