Evellyn Lima

E como o this funciona?

May 17, 2021

O this pra mim foi uma das partes mais confusas de entender quando comecei a estudar JavaScript, acho que foi tão difícil de entender por 2 motivos:

  1. Quando eu tinha dúvidas não tinha pra quem perguntar.
  2. As explicações que eu encontrava eram muito simples, na base do foo = "foo", e no final acabavam mais me confundindo do que me ajudando.

Por isso decidi escrever esse artigo, pra explicar o this do jeito que eu queria que tivessem me explicado quando eu estava aprendendo.

Acho que o que fica mais confuso no começo é que cada hora o this tem um valor diferente, então vou explicar o pq disso com alguns exemplos. O this é uma palavra reservada do JS, com ele você consegue ter acesso a algumas propriedades do contexto onde ele está inserido.

Vamos executar esse trecho de código e ver o que acontece:

function example() {
  return this
}

console.log(example())

Se você executar esse script pelo node o valor retornado é o globalThis:

GIF 01

Agora se você executar esse mesmo script no browser, o valor do this muda, pq o contexto mudou. Criei um arquivo HTML, importei esse script e abri o arquivo no browser, esse foi o valor que apareceu no console:

GIF 01

No contexto do browser, esse this é o objeto Window.

Mas pq? Pq o valor do this muda de acordo com o contexto onde ele é chamado. E nesse primeiro exemplo a gente tá acessando o this em um contexto global, ele não tá dentro de nenhum objeto, função ou evento, então o ambiente onde esse arquivo é executado é que define o valor do this.

Então se esse this estivesse dentro de uma função/evento o valor seria diferente? Sim, e dependeria apenas do contexto onde a gente inseriu ele, e não mais do ambiente onde o arquivo foi executado. Vou mostrar alguns exemplos.

objeto + função

O this sendo chamado dentro de uma função que faz parte de um objeto:

const example = {
  name: "Evellyn",
  getName: function() {
    console.log(this.name)
  },
}

example.getName() // a saída será: "Evellyn"

Nesse caso o this faz referência ao objeto no qual a função está inserida e por isso quando printamos this.name o valor exibido é “Evellyn”, que é o valor que foi definido na chave name desse objeto onde o this foi executado.

strict mode

Se o nosso código estiver rodando no strict mode as coisas mudam um pouco.

Quando nosso código estiver rodando nesse modo, o this chamado fora de um contexto terá o valor de undefined ao invés do valor globalThis (node) ou da Window (browser).

"use strict"

function example() {
  return this
}

console.log(example()) // undefined

bind

Nós podemos mudar o contexto do this conforme a nossa necessidade também, pra fazer isso podemos usar um método chamado bind, a documentação do JS diz que “O método bind() cria uma nova função que, quando chamada, tem sua palavra-chave this definida para o valor fornecido.”

const getName = function() {
  return this.name
}

const myInfo = {
  name: "Evellyn",
}

const otherPersonInfo = {
  name: "Nome aleatório",
}

const myName = getName.bind(myInfo)
const notMyName = getName.bind(otherPersonInfo)

console.log(myName()) // "Evellyn"
console.log(notMyName()) // "Nome aleatório"

Como podemos ver no exemplo acima, o valor do this muda de acordo com o contexto que é passado para ele pelo método bind. Mas como isso acontece? Ao usar o bind a engine do JS cria uma nova instância do método getName e define a variável passada por parâmetro como referência pro this.

arrow function

Dentro de uma arrow function o this faz referência ao escopo onde essa função foi criada. No nosso exemplo o this dentro da função example e dentro do objectExample representam o valor da Window pq o escopo no qual essas funções foram criadas é o escopo global.

const example = () => {
  console.log("example: ", this) // objeto Window do browser
}

const objectExample = {
  name: "Evellyn",
  getThis: () => {
    return console.log("objectExample: ", this) // objeto Window do browser
  },
}

example()
objectExample.getThis()

Mas se a gente criar uma função tradicional e dentro dela definirmos uma variável e tentarmos pegar ela com o this nós vamos conseguir, pq? Pq a arrow function foi criada dentro do contexto dessa função.

function Person() {
  this.age = 25
  this.sayAge = () => {
    console.log(this.age)
  }
}

const person = new Person()
person.sayAge() // 25

Além dessas mudanças, com arrow function nós não conseguimos mudar o valor do this como fizemos com o uso do bind no exemplo acima, nem conseguimos ter acesso ao objeto no qual o this está inserido como fizemos no primeiro exemplo pq dentro de uma arrow function nós não temos a chave this.

conclusão

O this pode causar bastante confusão no seu código, e na sua cabeça, então sempre que for usar ele e não souber exatamente o que está acontecendo é importante você ler a documentação, ou procurar uma resposta em alguma fonte confiável ou colega/amigo, pra entender se está usando ele da maneira correta e garantir que isso não vai causar algum comportamento inesperado na sua aplicação.


Eu sou a Evellyn Lima, desenvolvedora web [por acaso] desde 2014 e a favor de JS sem ponto e vírgula.
Twitter LinkedIn