我看了MutationObserver API,发现了不必要的复杂性,并为它编写了我的包装函数:
window.observeDom = (element, callback, config) => {
let conf = config || { childList: true };
const observer = new MutationObserver(callback.bind(element));
observer.observe(element, conf);
return observer;
};
虽然我比原始API更喜欢这个函数10倍,但我仍然想知道在重用observer
实例来观察不同的DOM节点时是否存在实际可测量的性能差异。你能解释一下吗?
答案 0 :(得分:1)
我不明白你的意思,但是如果你想使用单个回调来观察DOM中的多个不同线程,那么这个架构可能比为每个这样的线程提供另一个MutationObserver实例更有用。
考虑使用公共模式观察页面上的所有<a>
元素,因此需要单个函数来对变更任何这些元素做出反应。您可能会观察<body>
元素并将复杂性移至回调中,以确定某些突变是否影响您实际感兴趣的任何<a>
元素。但该决策逻辑是在Javascript中实现的,而不是本机运行在浏览器中。我敢打赌,这会对性能产生影响。
因此,您可能会观察每个<a>
元素。然后,您的包装器会创建与文档中的<a>
元素一样多的观察者实例。这会影响记忆力。并且浏览器必须迭代许多观察者来迭代每个观察者的观察节点的单项列表,这可能对性能产生另外的轻微影响。此外,通过在每次观察时将回调绑定到节点,您实际创建的回调实例与文档中的<a>
元素一样多。这又浪费了记忆力。
要以这种方式观察1000个<a>
元素,将有1000个观察者实例由浏览器管理,每个实例绑定到1000个不同绑定中的一个,但实际上是相同工作的函数实例。每个观察者都在控制要观察的一项节点列表。
现在,使用要注册的相同回调来观察要等待处理的一堆记录并不像看起来那么复杂。可以减少唯一的回调来处理预期的突变。它不必检查DOM以确定哪些元素已被变异以及在您的情况下这是否有趣(访问DOM始终被视为性能瓶颈)。
要使用建议的API观察同一组1000 <a>
元素,需要观察1个观察者实例,1个函数实例和一个包含1000个节点引用的列表,因此任何突变都会导致调用该单个函数。因此,在这种情况下,只有一件事需要在内存中管理1000次,并且要与实际观察者一起观察节点的关联。
总而言之,API稍微复杂一些,以适应广泛分布在您的文档上的许多节点的观察,而不会浪费Javascript中的时间和内存。我认为这比使用简单的API更有益,即使后者可能足以满足您的特定用例。