Skip to the solution
MediumFrontend6 min read

How would you use MutationObserver to detect when a third-party script injects new nodes into the DOM?

440 views

The problem

Question presented to candidate: "A third-party analytics script you don't control keeps injecting an ad banner div somewhere inside your page's content area, and you need to detect and remove it the moment it appears. How would you reliably catch that injection?"

What a strong answer should cover:

  • πŸ“Œ Interview term: MutationObserver β€” a real, built-in browser API that lets code .observe(targetNode, options) and receive a real callback whenever the DOM tree under that target genuinely changes β€” child nodes added/removed, attributes changed, or text content changed, depending on the configured options.
  • πŸ“Œ Interview term: the real, direct answer to the prompt β€” verified directly via jsdom (which, unlike ResizeObserver/IntersectionObserver, genuinely DOES implement MutationObserver): observing a target with { childList: true, subtree: true } genuinely detected a real, dynamically-injected <script> node appended anywhere under the target, reporting it in a real mutations array with type: "childList" and the injected node present in addedNodes.
  • πŸ“Œ Interview term: the real, asynchronous, batched callback timing β€” a precise answer names that MutationObserver callbacks genuinely fire ASYNCHRONOUSLY, batched as a real MICROTASK β€” verified directly, a mutation made synchronously did not appear in the log until AFTER the current synchronous script finished and a microtask was allowed to flush β€” several rapid mutations made in the same tick genuinely arrive together in ONE callback invocation, not one callback per mutation.
  • πŸ“Œ Interview term: { childList, subtree, attributes } options β€” a precise answer names that MutationObserver genuinely observes NOTHING by default β€” at least one of childList/attributes/characterData must be explicitly set to true, and subtree: true is genuinely required to catch a mutation happening on a DESCENDANT of the target, not just the target itself.
  • A precise answer names the real, practical response pattern for the prompt's own scenario: inside the callback, check each mutation's addedNodes for a match (by tag name, class, or a known selector) and call .remove() on it immediately β€” plus the real caveat that .disconnect() should eventually be called if the watch is no longer needed, to avoid an unnecessary real, ongoing observation cost.

Clarifying questions expected:

  • None β€” this is a definitional/practical question; directly demonstrating the real, verified detection of an injected node is the strong signal.

Code / implementation expected: Yes β€” a real, jsdom-verified MutationObserver detecting a dynamically injected node and an attribute change, plus proof of .disconnect() stopping further detection.

  • observers
  • tricky
  • real-world

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

6 min read Β· 8 sections

Run the code

Edit the code and run it here. Each console line with an expected value becomes a test.

JavaScriptReal, direct proof via jsdom: MutationObserver detects a dynamically injected node and an attribute change, fires asynchronously as a batched microtask, and disconnect() stops further detection

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 92 of 165 in JavaScript

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextMedium

Why must you pass the same function reference to removeEventListener?

Continue