Detectar mudanças no DOM com observadores de mutação

Em 2000, a API Muutation Events foi especificada para facilitar a reação dos desenvolvedores a mudanças em um DOM (por exemplo, DOMNodeRemoved, DOMAttrModified etc.).

Esse recurso não era amplamente utilizado por desenvolvedores da Web, mas representava um caso de uso muito conveniente e popular para as extensões do Chrome se eles quisessem realizar alguma ação quando algo na página mudasse.

Os eventos de mutação são úteis, mas, ao mesmo tempo, causam alguns problemas de desempenho. Os eventos são lentos e disparados com muita frequência, de forma síncrona, o que causa alguns bugs indesejados do navegador.

Introduzido na especificação DOM4, os DOM Mutation Observers (em inglês) vão substituir os eventos de mutação. Enquanto os eventos de mutação dispararam eventos lentos para cada mudança, os observadores de mutação são mais rápidos usando funções de callback que podem ser entregues após várias mudanças no DOM.

Você pode processar manualmente a lista de mudanças que a API oferece ou usar uma biblioteca, como Mutation Summary, que facilita essa tarefa e adiciona uma camada de confiabilidade sobre as mudanças que ocorreram no DOM.

Você pode começar a usar os Mutation Observers no Chrome Beta para detectar mudanças no DOM e estar pronto para usá-lo quando se tratar da versão estável (Chrome 18). Se você estiver usando os eventos de mutação descontinuados, basta migrar para a Mutation Observers.

Veja um exemplo de listagem de nós inseridos com eventos de mutação:

var insertedNodes = [];
document.addEventListener("DOMNodeInserted", function(e) {
    insertedNodes.push(e.target);
}, false);
console.log(insertedNodes);

E é assim que funciona com Mutation Observers:

var insertedNodes = [];
var observer = new MutationObserver(function(mutations) {
    mutations.forEach(function(mutation) {
    for (var i = 0; i < mutation.addedNodes.length; i++)
        insertedNodes.push(mutation.addedNodes[i]);
    })
});
observer.observe(document.documentElement, { childList: true });
console.log(insertedNodes);