Responda à mudança com Object.observe

Alex Danilo

Muitos frameworks JavaScript que usam MVC ou MDV precisam responder a mudanças nos objetos que modelam o estado dentro de um aplicativo da Web. Esse recurso é uma parte fundamental de um modelo de vinculação de dados.

Há várias maneiras diferentes de monitorar objetos JavaScript e propriedades DOM para acionar algum tipo de ação, mas a maioria das técnicas não é ideal por vários motivos, como desempenho etc.

Para melhorar a performance dos aplicativos da Web, um novo método chamado Object.observe() foi proposto ao TC39, o órgão de padrões que supervisiona o desenvolvimento do ECMAScript (JavaScript).

Object.observe() permite adicionar um ouvinte a qualquer objeto JavaScript que é chamado sempre que esse objeto ou as propriedades dele mudam.

Você pode testar essa opção agora na versão 25 do Chrome Canary.

Para testar esse recurso, ative a flag Enable Experimental JavaScript no Chrome Canary e reinicie o navegador. A flag pode ser encontrada em "about:flags", conforme mostrado na imagem abaixo:

Flags do Chrome.

Confira um exemplo simples de como configurar um observador em um objeto:

var beingWatched = {};
// Define callback function to get notified on changes
function somethingChanged(changes) {
    // do something
}
Object.observe(beingWatched, somethingChanged);

Quando o objeto "beingWatched" é modificado, ele aciona a função de callback "somethingChanged", que recebe uma matriz de mudanças aplicadas ao objeto.

Assim, o mecanismo do JavaScript fica livre para armazenar em buffer um número de mudanças e transmiti-las em uma única chamada para a função de callback. Isso ajuda a otimizar os callbacks para que o código possa fazer muitas manipulações de JavaScript, mas processe apenas alguns callbacks agrupando as atualizações.

A função de callback será acionada sempre que uma propriedade for adicionada, modificada, excluída ou reconfigurada.

Outra coisa muito legal ao observar matrizes é que, se uma matriz tiver passado por várias mudanças, é possível usar uma biblioteca auxiliar de resumo de mudanças para criar um conjunto de mudanças mínimo, para que o JavaScript do lado do cliente não precise verificar manualmente a matriz para verificar cada item.

É possível iterar por cada mudança com facilidade, fazendo algo como o seguinte na função de callback "somethingChanged":

function whatHappened(change) {
    console.log(change.name + " was " + change.type + " and is now " + change.object[change.name]);
}
function somethingChanged(changes) {
    changes.forEach(whatHappened);
}

A propriedade type identifica o que aconteceu com o objeto. Confira alguns exemplos de propriedades sendo definidas e o tipo associado no código abaixo.

beingWatched.a = "foo"; // new
beingWatched.a = "bar"; // updated
beingWatched.a = "bar"; // no change
beingWatched.b = "amazing"; // new

O bom dessa técnica é que todos os recursos inteligentes de monitoramento estão dentro do mecanismo JavaScript, o que permite que o navegador o otimize bem e libere o JavaScript para implementar a funcionalidade aproveitando esse recurso.

Outro recurso muito bom para desenvolvimento é a capacidade de usar Object.observe() para acionar o depurador sempre que um objeto muda. Para fazer isso, você usaria um código semelhante ao exemplo abaixo.

Object.observe(beingWatched, function(){ debugger; });

Confira uma ótima introdução em vídeo sobre Object.observe() que explica isso em detalhes.

Também há um texto descritivo disponível e um exemplo de trabalho aqui.

O órgão de padrões TC39 está buscando feedback sobre esse recurso. Teste-o e nos diga o que você achou.