Skip to content

Instantly share code, notes, and snippets.

Embed
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 `Object.observer()`](https://gist.github.com/ebidel/1b553d571f924da2da06).
Run it: http://jsbin.com/dukuluwufa/edit?html,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>
<output></output>
<script>
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 = performance.now();
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 = performance.now();
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 = performance.now();
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.
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.