Responda à mudança com Object.observe

Alex Danilo

Muitas estruturas de JavaScript que usam MVC ou MDV precisam responder a alterações nos objetos que modelam o estado em um aplicativo da Web. Esse recurso é uma parte fundamental de um modelo de vinculação de dados.

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

Para melhorar o desempenho de 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 listener a qualquer objeto JavaScript que é chamado sempre que esse objeto ou as propriedades dele mudam.

Faça o teste agora no Chrome Canary versão 25.

Para testar esse recurso, ative a sinalização Ativar JavaScript experimental no Chrome Canary e reinicie o navegador. A sinalização pode ser encontrada em "about:flags", como mostrado na imagem abaixo:

Sinalizações do Chrome.

Veja 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 "gettingWatched" é modificado, ele aciona a função de retorno de chamada "somethingChanged", que recebe uma matriz de alterações aplicadas ao objeto.

Portanto, o mecanismo JavaScript é livre para armazenar em buffer várias alterações e passar todas elas em uma única chamada para a função de retorno de chamada. Isso ajuda a otimizar os callbacks para que seu código possa fazer muitas manipulações de JavaScript, mas processar apenas alguns callbacks reunindo as atualizações em lotes.

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 várias mudanças feitas, é possível usar uma biblioteca auxiliar Change Summary para criar um conjunto mínimo de alterações. Assim, o JavaScript do lado do cliente não vai precisar verificar a matriz manualmente para verificar cada item.

Você pode iterar cada alteração facilmente, fazendo algo como o seguinte em sua função de retorno de chamada '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. Veja no código abaixo alguns exemplos de propriedades definidas e o tipo associado.

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

O melhor dessa técnica é que toda a inteligência de monitoramento está dentro do mecanismo JavaScript, que permite que o navegador otimize-o e libere seu JavaScript para implementar funcionalidades que aproveitam esse recurso.

Outro recurso muito bom para o desenvolvimento é a capacidade de usar Object.observe() para acionar o depurador sempre que um objeto mudar. Para fazer isso, use um código como o do exemplo abaixo.

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

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

Você também pode conferir um artigo descritivo disponível e um exemplo funcional.

O órgão de padrões TC39 quer receber feedback sobre esse recurso. Não deixe de testar e nos contar o que achou.