JavaScript Interview Questions — DOM and Event Questions

John Au-Yeung - Jan 24 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

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 and handling events.

What is a repaint and when does this happen?

A repaint happens when we change the look of an element without changing its size and shape.

It doesn’t cause reflow since its dimensions and position didn’t change.

The repainting process happens when an element changes the background color, change text color, or hide visibility.

How could we run some JavaScript when DOM is ready like $(document).ready?

We can put our scripts in the HTML body element. The DOM would be ready by the time the browser runs the script tag there.

Also, we can put our code inside the DOMContentLoaded event handler. The code inside will run only when the DOM is completely loaded.

For example, we can write the following:

document.addEventListener('DOMContentLoaded', () => {
  console.log('DOM loaded');
});
Enter fullscreen mode Exit fullscreen mode

We can also watch the readystatechange event by attaching a listener to it.

When the readyState is 'complete' , then we know the DOM has loaded.

For instance, we can write the following code to do that:

document.onreadystatechange = () => {
  if (document.readyState == "complete") {
    console.log('DOM loaded');
  }
}
Enter fullscreen mode Exit fullscreen mode

What is event bubbling? How does event flow?

Event bubbling means that the event propagates from the originating element to its parent, grandparent, and all the way up to the window object.

The browser will run all event handlers that are attached to all the parent elements of the originating element in addition to the originating element.

For example, if we have the following HTML:

<div>
  <p>
    <button>Click</button>
  </p>
</div>
Enter fullscreen mode Exit fullscreen mode

Then when we attach event listeners to all the elements and document and window as follows:

const div = document.querySelector('div');
const p = document.querySelector('p');
const button = document.querySelector('button');

button.onclick = () => {
  alert('button clicked');
}

p.onclick = () => {
  alert('p clicked');
}

div.onclick = () => {
  alert('div clicked');
}

document.onclick = () => {
  alert('document clicked');
}

window.onclick = () => {
  alert('window clicked');
}
Enter fullscreen mode Exit fullscreen mode

and click the Click button, then we’ll see all the alerts listed in the same order that we listed in the code.

So we get ‘button clicked’, ‘p clicked’, ‘div clicked’, ‘document clicked’ and ‘window clicked’ alerts displayed in that order.

How would we destroy multiple list items with one click handler?

We can use event delegation to do that.

It works by listening to the clicks of the parent element of the list. Then we can check which child has been clicked in the click handler and then remove that element from the DOM.

For example, if we have the following HTML:

<ul>
    <li>first</li>
    <li>second</li>
    <li>third</li>
    <li>forth</li>
    <li>Fifth</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

Then we can write the following JavaScript code to remove the li elements that we clicked on as follows:

document.querySelector('ul').addEventListener('click', (e) => {
  const elm = e.target.parentNode;
  elm.removeChild(e.target);
  e.preventDefault();
});
Enter fullscreen mode Exit fullscreen mode

In the code above, we get the parentNode property of the element we clicked on to get the ul.

Then we can call removeChild on it to remove the li that we clicked on since e.target is the element that we clicked on, which is the li.

Finally, we call preventDefault to stop event propagation.

Create a button that is destroyed by clicking on it but two new buttons are created in its place.

We can do that by using the logic above for removing the button that we clicked on.

Then we add use createElement and appendChild to create more buttons and add them to the list.

For example, given the following HTML:

<div>
  <button>button</button>
</div>
Enter fullscreen mode Exit fullscreen mode

We write the following JavaScript code to add 2 buttons and then remove the original button that was clicked on by attaching a click listener to the div and then manipulating the buttons:

document.querySelector('div').addEventListener('click', (e) => {
  if (e.target.tagName === 'DIV') {
    return;
  }
  const elm = e.target.parentNode;
  e.preventDefault();

  const btn = document.createElement('button');
  btn.innerHTML = 'button';

  const btn2 = document.createElement('button');
  btn2.innerHTML = 'button';

  elm.appendChild(btn);
  elm.appendChild(btn2);
  elm.removeChild(e.target);
});
Enter fullscreen mode Exit fullscreen mode

In the code above, we check if we actually clicked on a button.

If we did, then we proceed to create 2 buttons. Then we call appendChild on the parentNode of the button that was clicked, which is the div, to attach the 2 buttons.

Then we call removeChild on e.target , which should the button since we checked it’s not a div, to remove the button.

Conclusion

We can watch if the DOM is ready with readystatechange or DOMContentLoaded events.

Event bubbling happens when an element’s events propagate up the DOM tree.

appendChild and removeChild are used to add and remove elements. We can handle events of multiple child elements with event delegation.

A repaint happens when we change the look of an element without changing its geometry.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .