Javascript: Contexto das Funções

Observei alguns erros comuns ao utilizar funções, ou métodos, como parâmetros para outras funções. Como assim? Vislumbre o código abaixo:

function testando() {
   alert("teste");
}

function outroTestando(f) {
   f();
}

outroTestando(testando);

Sim, caso você não saiba, em Javascript isto é possível. Será apresentado um alerta com a palavra “teste” na tela. Mas o que isto tem a ver com o título deste post? Agora imagine que você tem um objeto(a classe abaixo está definida usando a biblioteca Prototype:

var MinhaClasse = Class.create(); // Class.create é da Prototype.
MinhaClasse.prototype = {
initialize: function() {
// construtor.
// definindo um atributo para esta classe.
    this.umatributo = "testando";
},

  // Um método da minha classe.
  meuMetodo: function() {
    alert(this.umatributo);
  }
}

// Uma função externa à classe.
function funcaoTeste(f) {
f();
}

// Instanciando um objeto do tipo MinhaClasse.
var minhaClasse = new MinhaClasse();
funcaoTeste(minhaClasse.meuMetodo);

O que o alerta vai imprimir? Vazio, nada, undefined, null… Porque? O atributo definido por “this.umatributo” perdeu o contexto no qual estava, que era o da classe MinhaClasse. Agora este atributo está no contexto da função “funcaoTeste” e esta função não possui um atributo com este nome. Entendeu? Mas porque eu falo isso? Porque você faz códigos como este muito em Ajax, quando você passa a função de “callback”, lembra? Portanto, tome cuidado quando for passar como função de callback um método de uma classe sua, pois todos os atributos referenciados com “this” podem não ter os valores que você esperava.

Agora mais uma, pra ficar mais claro, e para você entender melhor como esta linguagem é bastante dinâmica e interessante:

var MinhaClasse = Class.create(); // Class.create é da Prototype.

MinhaClasse.prototype = {

initialize: function() {
// construtor.
// definindo um atributo para esta classe.
this.umatributo = "testando";
},

// Um método da minha classe.
meuMetodo: function() {
alert(this.umatributo);
}

}

var MinhaOutraClasse = Class.create();
MinhaOutraClasse.prototype = {

initialize: function() {
// construtor.
// definindo um atributo para esta classe.
this.umatributo = "testando na nova classe.";
}
}
var minhaClasse = new MinhaClasse();
var minhaOutraClasse = new MinhaOutraClasse();

minhaOutraClasse.meuMetodo = minhaClasse.meuMetodo;
minhaOutraClasse.meuMetodo();

Isso mesmo, vai ser impresso “testando na nova classe”. 🙂

×