Skip to content

Instantly share code, notes, and snippets.

Last active May 18, 2023 01:05
  • Star 20 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
MutationObserver vs. Proxy to detect .textContent changes
This demo shows two ways to detect changes to a DOM node `.textContent`, one
using a `MutationObserver` and the other using an ES2015 `Proxy`.
From testing, a `Proxy` appears to be 6-8x faster than using a MO in Chrome 50.
**Update**: removing the `Proxy` altogether speeds up the MO to be inline with the Proxy.
This has something to do with how the browser queues/prioritizes Proxies over MO.
Why is this useful? One could imagine creating a primative data-binding system
around the `Proxy` approach or using it to [polyfill ``](
Run it:,output
<p><button onclick="update()">update .textContent</button></p>
<p>[MO]'d node content: <span id="source"></span></p>
<p>[Proxy]'d node content: <span id="source-proxied"></span></p>
let start, finish, start2, finish2;
// Watch accesses/sets on a DOM element property.
function watchPropsOn(el, prop, callback=null) {
return new Proxy(el, {
set(target, propKey, value, receiver) {
if (prop === propKey) {
let finish2 =;
out.innerHTML += `Proxy took: ${finish2 - start2}ms<br>`;
console.log(`Proxy set .${propKey} to ${value}`);
target[propKey] = value;
function observe(target) {
// create an observer instance
let observer = new MutationObserver(mutations => {
let finish =;
out.innerHTML += `MutationObserver took: ${finish - start}ms<br>`;
mutations.forEach(mutation => {
if (mutation.addedNodes.length) {
console.log(`MutationObserver observed childList as ${target.textContent}`)
observer.observe(target, {childList: true});
function update() {
out.innerHTML = '';
start = start2 =;
proxy.textContent = source.textContent = Math.random();
let source = document.querySelector('#source');
let proxiedSource = document.querySelector('#source-proxied');
let out = document.querySelector('output');
observe(source); // setup MO
let proxy = watchPropsOn(proxiedSource, 'textContent'); // setup proxy.
Copy link

snuggs commented Feb 11, 2017

@ebidel Thanks for this one! Shouts in my README (if you don't mind). #salute 🙏

Using them in a textContent Relay MutationObserver binding.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment