Regra padrão (default binding)
Cenário 1
console.log('Contexto global', this); // window (no navegador)
No contexto global, this referencia o objeto global (window no navegador).
Cenário 2
function show() {
console.log('Dentro de função comum', this);
}
show(); // window
Em uma função comum chamada diretamente, this também aponta para o objeto global.
Conclusão 1
Quando a função é chamada sem nenhum contexto explícito, this assume o objeto global (window).
Vínculo implícito (implicit binding)
Cenário 3
function display() {
console.log(this.val);
}
const objeto = {
val: 42,
display
};
objeto.display(); // 42
Ao chamar objeto.display(), o this dentro de display aponta para o objeto objeto.
Cenário 4
const outroObjeto = {
objeto,
val: 100
};
outroObjeto.objeto.display(); // 42
Mesmo com dois níveis de aninhamento, this se refere ao objeto mais próximo na cadeia de chamada (no caso, objeto).
Conclusão 2
Quando uma função é invocada como método de um objeto, this aponta para o objeto que contém a referência imediata da função.
Perda de vínculo (losing this)
Cenário 5
function display() {
console.log(this.val);
}
const objeto = {
val: 42,
display
};
const copia = objeto.display;
copia(); // undefined
Ao atribuir a função a uma variável e chamá-la sem cnotexto, this volta para o objeto global (ou undefined em modo estrito), perdendo a referência original.
Cenário 6
const obj1 = {
texto: 'primeiro',
fn: function () {
return this.texto;
}
};
const obj3 = {
texto: 'terceiro',
fn: function () {
const f = obj1.fn;
return f();
}
};
console.log(obj3.fn()); // undefined
Mesmo dentro do método obj3.fn, a função f perde o vínculo com obj1 e this não aponta para nenhum objeto esperado.
Conclusão 3
Se uma função é extraída do objeto e chamada independentemente, o vínculo implícito é perdido. Isso ocorre porque a referência ao objeto é removida no momento da chamada.
Vínculo explícito (explicit binding)
Cenário 7
const copia = objeto.display.bind(objeto);
copia(); // 42
Usando bind, fixamos o this no objeto desejado, resolvendo a perda de contexto.
Cenário 8
const obj3Corrigido = {
texto: 'terceiro',
fn: function () {
const f = obj1.fn;
return f.call(this);
}
};
console.log(obj3Corrigido.fn()); // 'terceiro'
Com call (ou apply) psasamos o this desejado dinamicamente. A diferença entre eles é apenas na passagem de argumnetos: call(this, arg1, arg2) e apply(this, [arg1, arg2]).
Uso especial de apply
const lista = ['a', 'b'];
const elementos = [0, 1, 2];
lista.push.apply(lista, elementos);
console.log(lista); // ['a', 'b', 0, 1, 2]
// Em ES6+: lista.push(...elementos)
Cenário 9
class Exemplo {
nome = 'padrão';
falar() {
console.log(this.nome);
}
}
const inst = new Exemplo();
const metodo = inst.falar;
metodo(); // undefined (perda de contexto em classes)
Métodos de classe também sofrem perda de this ao serem desvinculados – problema comum em React, por exemplo.
Vínculo com new (new binding)
Cenário 10
function Pessoa(nome) {
this.nome = nome;
}
const p = new Pessoa('Ana');
console.log(p.nome); // Ana
Quando uma função é chamada com new, um novo objeto é criado e this aponta para esse objeto.
Cenário 11
class Animal {
constructor(tipo) {
this.tipo = tipo;
}
}
const a = new Animal('Gato');
console.log(a.tipo); // Gato
O mesmo se aplica a classes, onde o constructor configura o objeto com this.
Conclusão 4
O vínculo explícito (call/apply/bind) tem prioridade sobre o vínculo implícito, e o new binding também sobrepõe o implícito.
Modo estrito (strict mode)
Cenário 12
function estrito() {
'use strict';
console.log('Modo estrito:', this);
}
estrito(); // undefined
Em modo estrito, o this padrão é undefined em vez do objeto global.
Arrow functions
Cenário 13
const arrow = () => {
'use strict';
console.log('Arrow em strict:', this);
};
arrow(); // window (não muda)
Arrow functions ignoram o modo estrito e mantêm o this do escopo léxico (onde foram definidas).
Cenário 14
const getVal = () => {
console.log(this, this.valor);
};
const objArrow = {
valor: 10,
getVal
};
objArrow.getVal(); // window, undefined
Arrow functions não são vinculadas implicitamente – o this permanece o do escopo externo.
Cenário 15
objArrow.getVal.bind(objArrow)(); // window, undefined
objArrow.getVal.call(objArrow); // window, undefined
Nem mesmo vínculo explícito altera o this de uma arrow function.
Cenário 16
const Construtor = () => {
this.prop = 'teste';
};
const inst = new Construtor(); // TypeError: Construtor is not a constructor
Arrow functions não podem ser usadas como construtores (com new).
Cenário 17
class Usuario {
nome = 'Maria';
saudacao = () => {
console.log(this.nome);
};
}
const u = new Usuario();
u.saudacao(); // Maria
Usando arrow function como método de classe, o this é capturado no momento da definição, evitando perda de contexto.
Conclusão 5
Arrow functions não permitem reatribuição de this (nem implícita, nem explícita). Elas herdam o this do escopo pai no momento da criação.
Prioridade das regras
Ordem de precedência (da maior para a menor):
- Arrow functions (não podem ser alteradas)
- new binding (cria novo objeto)
- Explicit binding (
bind,call,apply) - Implicit binding (chamada como método)
- Default binding (global ou
undefinedem strict)