As múltiplas personalidades do this em JavaScript

Postado em 07. mai, 2012 por Ricardo Valeriano em JavaScript, Web Design

Se você já escreveu algum código JavaScript, não deve mais achar estranho quando alguém atribui uma função a uma variável. Mas o que exatamente acontece quando você faz isso? Em JavaScript, as funções podem ser passadas como parâmetros para outras funções, retornadas como valor e, como já dito, referenciadas por variáveis. A linguagem trata as funções como cidadãs de primeira classe.

O JavaScript representa funções como objetos. Quando atribuímos uma função a uma variável, estamos criando uma referência para um objeto do tipo function. Podemos ver isso de forma clara utilizando o operador typeof. O exemplo abaixo cria uma função e a atribui a variável chamada apresentar, que recebe como parâmetro um objeto com os atributos nome e email. Vamos invocar a função e a seguir usar o operador typeof para inspecionar o tipo que é referenciado pela variável usada para guardar a função:

var apresentar = function(pessoa) {
     console.log("Eu sou "+ pessoa.nome +" e meu email é: "+ pessoa.email);
}
 
apresentar({nome: "Ricardo", email: "ricardo.valeriano@caelum.com.br"});
// Eu sou Ricardo e meu email é: ricardo.valeriano@caelum.com.br
 
typeof(apresentar); // "function"

Quando invocamos uma função com o operador (), estamos utilizando uma forma de invocação chamada por alguns de invocação simples. A maneira como uma função é invocada tem efeito direto sobre como a palavra chave this é “atribuída” no corpo da função.

Quando seu código JavaScript é executado em um navegador, uma variável global chamada window é criada para representar a própria janela do navegador. E quando a forma simples de invocação é usada, o objeto referenciado por this é equivalente ao window, veja:

typeof(window); // "object"

console.log(window); // DOWWindow

var verificandoWindow = function() {
    console.log(this); 
    console.log(this === window);
}
verificandoWindow();
// DOWWindow, true

Notou que o tipo referenciado por window é object? Podemos criar nossa própria instância de object usando a chamada notação literal, que é a que foi usada para criar o parametro passado na invocação da função apresentar no nosso primeiro exemplo.

A variável window é uma referência para um objeto e podemos adicionar atributos a ele! Quando criamos uma variável fora de uma função (ou seja no escopo

  • global
  • ), automaticamente um atributo com o mesmo nome da variável é criado em window para referenciar o objeto atribuído a nova variável. Quando tentamos acessar o valor dessas variáveis, estamos, na verdade, recuperando o valor de um atributo de window. Veja o exemplo a seguir:

    var todosPodemMeVer = "porque sou um atributo de window";
    console.log(window.todosPodemMeVer);
    // porque sou um atributo de window
    
    var pessoa = {
       nome:  "Ricardo",
       email: "ricardo.valeriano@caelum.com.br" 
    }
     
    console.log(pessoa.nome);
    // Ricardo
    
    console.log(window.pessoa === pessoa);
    // true
    

    Toda função tem acesso à palavra chave this. Vamos usar isso para obter informações sobre esse objeto. Vamos criar as propriedades nome e email em window e alterar a função para buscar os valores usando atributos presentes em this, e não mais do objeto recebido como argumento:

    var nome = "João da Silva";
    window.email = "joao@da.silva";
     
    var apresentar = function() {
        console.log(this === window);
        console.log("Eu sou "+ this.nome +" e meu email é "+ this.email);
    }
    
    apresentar();
    // true
    // Eu sou João da Silva e meu email é joao@da.silva
    

    Veja que criamos um atributo novo chamado email para o objeto referenciado por window. Um atributo pode referenciar qualquer objeto, inclusive funções. Para ilustrar, vamos criar um novo atributo chamado quemSouEu em pessoa, que é uma referência para a função apresentar do exemplo anterior. Dessa forma, será possível invocar essa função diretamente a partir do objeto pessoa.

    var pessoa = {
       nome:  "Ricardo",
       email: "ricardo.valeriano@caelum.com.br" 
    }
    

    Mas a função usa internamente a variável this para fazer seu trabalho, certo? Será que isso vai continuar funcionando? Repare a saída:

    pessoa.quemSouEu = apresentar;
    pessoa.quemSouEu();
    // false
    // Eu sou Ricardo e meu email é ricardo.valeriano@caelum.com.br
     
    apresentar();// Agora novamente invocando a função com o operador ()
    // true
    // Eu sou João da Silva e meu email é joao@da.silva
    

    Uma função referenciada por um atributo de um objeto pode ser invocada como um método daquele objeto, a palavra chave this é atribuída ao objeto onde a função foi invocada.

    Uma outra forma de executar uma função no contexto de um objeto específico é invocando o método call disponível em todo objeto do tipo function. Esse método possibilita definir o objeto referenciado por this no momento da invocação:

    apresentar.call(pessoa);
    // false
    // Eu sou Ricardo e meu email é ricardo.valeriano@caelum.com.br
    

    Mas não pense que acabou! Existem ainda outras formas de invocar funções que interferem em como a palavra this é atribuída. Por exemplo, o operador new pode ser utilizado em associação com o operador () para invocar qualquer função, isso vai fazer com que o this seja atribuído a um novo objeto. O retorno da função também pode ser alterado por essa forma de invocação. Você lerá sobre esses detalhes na segunda parte desse artigo.

    Ricardo Valeriano

    Mais sobre o autor

    Tags: , ,

    9 Respostas para “As múltiplas personalidades do this em JavaScript”

    1. Davi

      07. mai, 2012

      Muito legal a postagem, recentemente escrevi também um post questionando sobre o Javascript ser o padrão da web e superar até mesmo linguagens como PHP com Node.js etc.
      http://shar.es/2vFUb

    2. wedenson barros freitas

      07. mai, 2012

      Excelente post muito obrigado.

      Sozinho se chega mais rápido mais juntos vamos mais longe.

    3. Flavio Sakamura

      07. mai, 2012

      Parabens!!!!! Nenhuma linguagem é facil, kkkk.

    4. Caio Ribeiro Pereira

      07. mai, 2012

      Até animando o pessoal que curte Node.js, segue meu novo post apresentando 3 formas de trabalhar com Node.js é bem bacana e vale a pena conferir, principalmente para quem trabalha com Ruby, Python, Java, C#

      http://www.udgwebdev.com/3-maneiras-de-trabalhar-com-node-js/

    5. Vinicius Maia

      07. mai, 2012

      Muito bom!!!

      Parabéns

    6. Ricardo Valeriano

      11. mai, 2012

      Muito obrigado senhores. Fiquem ligados que em breve teremos mais detalhes sobre essas e outras características da linguagem! =)

    Trackbacks/Pingbacks

    1. As múltiplas personalidades do this em JavaScript | Backslashes - maio 7, 2012

      [...] mais no posto originalmente publicando no blog da Caelum. Like this:LikeBe the first to like this [...]

    2. As múltiplas personalidades do this em JavaScript | blog.caelum.com.br « Fernando Giorgetti - maio 11, 2012

      [...] http://blog.caelum.com.br/as-multiplas-personalidades-do-this-em-javascript/ [...]

    3. Conhecendo o operator new e os protótipos no JavaScript | blog.caelum.com.br - maio 17, 2012

      [...] var p = Pessoa(), serão criadas as variáveis nome e email em window! Isso porque, como vimos no post anterior, quando uma função é invocada de forma simples, a palavra chave this é associada com [...]

    Deixar uma Resposta