Entendendo o ‘this’ no JavaScript    

JavaScript é uma linguagem realmente interessante, e todo mundo que queira ser desenvolvedor Web deve ter essa linguagem como pré-requisito. Mas ela tem características um tanto quanto diferentes de uma linguagem como o C#. Não entender essas características faz com que pessoas tenham enorme dificuldade para entender como usar bibliotecas JavaScript, como JQuery ou KnockoutJS. Ou faz as pessoas fazerem milhares de linhas de script para fazer uma página web um pouco mais dinâmica.

Hoje então vou falar de mais uma característica do JavaScript: o operador this.

Como em qualquer linguagem que tenha esse operador, no JavaScript o this faz referência ao contexto atual da execução. Ou seja, caso você esteja desenvolvendo uma classe, o this fará referência à classe, ou ao objeto criado a partir dessa classe.

Mas no JavaScript, o this também tem uma característica totalmente diferente. No JS a gente consegue alterar o contexto do this, ou seja, é possível a gente mudar o que o JavaScript entende como contexto atual.

Por exemplo, se você já utilizou JQuery, já reparou como o this sempre é algo diferente? Veja o exemplo abaixo:

   1: //Vai sair Window
   2: alert(this);
   3:  
   4: var dados = [{ Nome: "Nome 1", Idade: "25" },
   5:             { Nome: "Nome 2", Idade: "23"}];
   6:  
   7:  
   8: $().ready(function() {
   9:     $("#link").click(function() {
  10:         //Vai sair o ID da tag A e não do Window
  11:         alert(this.id);
  12:     });
  13:  
  14:     $(dados).each(function() {
  15:         //Nesse contexto o this vai ser cada item do array.
  16:         alert("Nome: " + this.Nome + " - Idade: " + this.Idade);
  17:  
  18:     });
  19: });

Veja que para cada situação, o Alert vai exibir uma informação, mesmo que eu não esteja trabalhando em contextos diferentes, não estou utilizando classes, por exemplo.

O que está acontecendo no caso acima é que o JQuery está alterando o contexto this, para ficar mais fácil de trabalhar. Você já deve ter percebido que se eu quiser fazer um for manual no meu array, o this não vai ser cada item do array. Ou seja, o código abaixo vai exibir duas vezes o alert Window:

   1: for (var i = 0; i < dados.length; i++) {
   2:    alert(this);
   3: }

Então como eu posso alterar o meu contexto para conseguir simular o que o JQuery faz com o método $.each e demais métodos? Isso é feito através dos métodos apply ou call.

Conhecendo os métodos Apply e Call no JavaScript

Apply e Call são métodos internos do JavaScript disponíveis para qualquer método ou classe criada por você. A utilização deles é exatamente igual, mudando apenas a forma que é definido o segundo parâmetro. O apply recebe como segundo parâmetro um array de argumentos, enquanto o call recebe uma lista de parâmetros (como o ParamArray do C#).

Com esses métodos você consegue chamar métodos de uma forma diferentes, como o Invoke na classe MethodInfo do .Net. Esse método tem a capacidade de você definir qual é o contexto do this dentro do método que está sendo invocado.

A utilização de ambos se dá da seguinte forma:

   1: AlgumMetodo.call([contexto do this], param1,param2,param3);
   2: AlgumMetodo.apply([contexto do this], [param1,param2,param3]);

Perceba que a única diferença é o segundo parâmetro, que no call é uma lista de parâmetros e no apply é um único parâmetro do tipo array contendo os parâmetros no array.

Então como eu simulo o método JQuery $.each, por exemplo?

   1: var dados = [{ Nome: "Nome 1", Idade: "25" },
   2:             { Nome: "Nome 2", Idade: "23"}];
   3:  
   4:  
   5:  
   6: function exibirItens() {
   7:     alert("Nome: " + this.Nome + " - Idade: " + this.Idade);
   8: }
   9:  
  10: for (var i = 0; i < dados.length; i++) {
  11:     exibirItens.apply(dados[i]);
  12: }   

Se você testar o código acima, verá que no meu método exibirItens o this passa a ser cada item do meu array dados. Isso porque estou invocando meu método através do método apply, e estou passando no meu primeiro parâmetro o item atual do array. Não estou passando nada no segundo parâmetro porque meu método não espera parâmetros. Se eu fosse utilizar o call nada mudaria (apenas o aply pelo call, claro).

Agora que vimos como é possivel alterar o contexto do this, podemos criar métodos que recebam “delegates” (para falar na língua do .Net) como parâmetros e fazer alguns truques.

Por exemplo, baseado no código acima, vamos criar um método chamado paraCada que vai ter o mesmo comportamento do método $.each do JQuery.

   1: var dados = [{ Nome: "Nome 1", Idade: "25" },
   2:              { Nome: "Nome 2", Idade: "23"}];
   3:  
   4:  
   5: //Coleção é meu array com os dados que quero receber
   6: //Acao é o meu método que quero executar para cada item
   7: function paraCada(colecao,acao) {
   8:    for (var i = 0; i < colecao.length; i++)
   9:        acao.apply(colecao[i]);
  10: }
  11: //Aqui eu faço uso do meu método.
  12: paraCada(dados, function() {
  13:    alert("Nome: " + this.Nome + " - Idade: " + this.Idade);
  14: });

E está pronto! Um método como o $.each, Pense nas possibilidades, são muitas.

Bom, era isso! Acredito que para qualquer pessoa que quer ficar bom em JavaScript, esse conceito é muito importante.

Abraços e até o próximo!

20. maio 2011 23:43 by Frederico B. Emídio | Comments (0) | Permalink
Comments are closed

Sobre mim

Minha Imagem

Meu nome é Frederico Batista Emídio, trabalho com desenvolvimento de sistemas profissionalmente a oito anos, porém, já faço sites pessoais a pelo menos dez anos.

Para saber mais clique aqui.

Páginas

Calendário

<<  dezembro 2018  >>
seteququsedo
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

Visualizar posts em um Calendário
Sigua @fredemidio

MCP Asp.NET