terça-feira, 17 de fevereiro de 2009

Chamada a métodos no Js.

Este post é do tipo "um código vale mais do que mil palavras", assim sendo dificilmente você vai aprender alguma coisa apenas vendo o código escrito. Porém se você pegar cada pequeno bloco de código e rodar (O que pode ser feito, acredito, até com o firebug), você vai provavelmente entender os tipos possíveis de chamada em js e o que acontece com a palavra-chave "this" em cada um dos tipos. Podemos entender isso como qual o escopo no qual a função é rodada.

Vale uma ressalva de que na maioria, o conteúdo que escrevo aqui, aprendi no excelente livro que recomendo: Javascript: The Good Parts - O'REILLY, Douglas Crockford.

Bão, ao código...

O Js é uma linguagem atípica, herança por "prototype", sem classes, funções são objetos, vinculação tardia da palavra chave "this", etc... Por conta disso muita gente (eu inclusive) que começa a trabalhar com ele não entende nada. Assim vejo que é importante esclarecer aspectos "simples" da linguagem, como o que acontece quando chamamos uma função.

Aqui vão exemplos de quatro tipos de chamada:

Chamada á Função

// quando uma função não pertence a nenhum método...
function ola() {
document.writeln('ola
');
// o this neste caso é vinculado ao objeto global.
document.writeln(this);
}
ola();

####### com funções internas
/*
já no caso da função estar dentro de uma outra é necessário
uma "solução de contorno" para ter acesso às propriedades da externa.
*/
var ola2 = function() {
var that = this;
this.texto = "ola";
var fala = function() {
document.writeln(that.texto + "2
");
// segundo o livro, se usasse this direto aqui dentro não
// funcionaria pois ele ficaria vinculado ao objeto global.
// mas no exemplo abaixo, funciona.
document.writeln(this.texto + "---2
");
this.texto2 = 'aaaaaa';
}
fala();
document.writeln('texto2:' + this.texto2 + "
");
}
//ola2.fala(); -> daria erro pois não foi ligado ao this de ola2, é apenas funçao interna.
ola2();


Chamada ao Construtor
* esta maneira é indicada como a "pior dos dois mundos", pois imita uma linguagem com classes, mas não tem, e não deixa claro o uso do "prototype".

var Pessoa = function(nome) {
this.nome = nome;
}
/*
chamada ao construtor:
um novo objeto é criado com um link escondido para o valor do prototype da função
*/
p = new Pessoa("Fulano");
// veja que o método foi adicionado depois do objeto ser criado
Pessoa.prototype.escreveNome = function() {
document.writeln('+++++'+this.nome+'+++++
');
}
// procura em p, não tem, busca no Pessoa.prototype...
p.escreveNome();

p.escreveNome = function() {
document.writeln('-----'+this.nome+'-----
');
}

// procura em p, tem, usa o dele mesmo
p.escreveNome();

// remove o método do objeto p
delete(p.escreveNome);

// procura em p novamente, não tem pois foi apagado, usa novamente o do prototype
p.escreveNome();



Chamada ao Método

var o = {
linha:"",
aumentaLinha: function() {
this.linha += "---";
},
mostraLinha: function() {
document.writeln(this.linha + '0' + this.linha + '
');
}
}

// a vinculação tardia do "this" ao objeto ocorre apenas na chamada ao método.
for(var a = 0; a<30; a++) {
// duas maneiras de se chamar o mesmo método:
o.mostraLinha();
o['aumentaLinha']();
}

Chamada Com Apply

// apply é um método presente em todas funções de js.
// lembrando que as funções de js são objetos e podem ter métodos.
mostraNome = function(extra) {
document.writeln("this.nome: " + this.nome + "
");
document.writeln("param extra: " + extra + "
");
}
mostraNome();
document.writeln("valor de mostraNome.apply:" + mostraNome.apply + "
");
document.writeln("
");
/*
apply chamará o método mostraNome, vinculando o this ao objeto passado
no primeiro parâmetro. E e ele vai passar para o mostra nome o array
de parâmetros passado no segundo parâmetro.
*/
mostraNome.apply({nome:"João "},["pereira dos santos"])
//

Nenhum comentário:

Postar um comentário