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
), 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
9 Respostas para “As múltiplas personalidades do this em JavaScript”
Trackbacks/Pingbacks
-
-
maio 7, 2012
[...] mais no posto originalmente publicando no blog da Caelum. Like this:LikeBe the first to like this [...]
-
-
maio 11, 2012
[...] http://blog.caelum.com.br/as-multiplas-personalidades-do-this-em-javascript/ [...]
-
-
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 [...]

ASSINE NOSSO RSS
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
wedenson barros freitas
07. mai, 2012
Excelente post muito obrigado.
Sozinho se chega mais rápido mais juntos vamos mais longe.
Flavio Sakamura
07. mai, 2012
Parabens!!!!! Nenhuma linguagem é facil, kkkk.
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/
Vinicius Maia
07. mai, 2012
Muito bom!!!
Parabéns
Ricardo Valeriano
11. mai, 2012
Muito obrigado senhores. Fiquem ligados que em breve teremos mais detalhes sobre essas e outras características da linguagem! =)