Funções de seta e a palavra-chave `this` em JavaScript

Última atualização: 02/10/2026
  • As funções de seta fornecem uma sintaxe concisa e capturam this lexicalmente a partir do seu âmbito circundante, em vez de criarem a sua própria ligação.
  • O valor de this Em funções regulares, depende de como elas são chamadas, afetando funções, métodos, construtores, classes e callbacks.
  • As funções de seta são ideais para callbacks e métodos de array, mas são uma escolha ruim para métodos de objeto, manipuladores de eventos DOM e construtores.
  • Entendendo quando this A distinção entre funções dinâmicas e lexicais é essencial para evitar erros sutis e para escolher entre funções de seta e funções tradicionais.

Funções de seta e o uso de `this` em JavaScript

Se você já fez login this Se você já usou funções JavaScript diferentes e obteve resultados completamente distintos, saiba que não está sozinho. Muitos desenvolvedores se deparam com casos em que um método imprime o objeto esperado, enquanto uma função de seta imprime... windowE uma seta aninhada repentinamente "magicamente" aponta de volta para o objeto circundante. Entender por que isso acontece é a chave para escrever código previsível e livre de erros.

Funções de seta e as this A formatação de palavras-chave é uma das combinações mais importantes (e incompreendidas) do JavaScript moderno. As funções de seta parecem apenas uma sintaxe mais curta, mas internamente elas mudam a forma como... this É assim que funciona o gerenciamento de callbacks, como eles se comportam e até mesmo quando você deve ou não usá-los como métodos. Vamos analisar tudo passo a passo, da sintaxe ao contexto de execução, usando linguagem simples e muitos exemplos práticos.

Sintaxe de função de seta sem confusão

As funções de seta são expressões de função escritas com o => sintaxe em vez de function palavra chave. Conceitualmente, você pode pensar nelas como uma forma compacta de escrever: “receba esses parâmetros, avalie essa expressão ou bloco de código e retorne um valor”. No fundo, elas ainda são funções, mas se comportam de maneira diferente em vários aspectos importantes.

A função de seta mais básica corresponde diretamente a uma expressão de função regular. Por exemplo, esta expressão de função clássica:

const multiplyByTwo = function (value) { return value * 2; };

Pode ser reescrito como uma função de seta assim:

const multiplyByTwo = (value) => { return value * 2; };

As funções de seta se destacam quando o corpo é uma expressão única. Se o corpo da requisição for apenas uma instrução que retorna algum valor, você pode omitir tanto as chaves quanto o operador explícito. return, permitindo um retorno implícito:

const multiplyByTwo = value => value * 2;

Quando houver exatamente um parâmetro, você pode omitir os parênteses que o envolvem, mas apenas nesse caso específico. So x => x * 2 É válido, mas se você tiver zero ou vários parâmetros, deve manter os parênteses:

  • Parâmetros zero: () => 42
  • Um parâmetro: x => x * 2 or (x) => x * 2
  • Dois ou mais parâmetros: (x, y) => x + y

Quando precisar de mais de uma frase no corpo do texto, você deve usar chaves e uma expressão explícita. return. Nessa situação, as funções de seta se comportam como funções regulares em relação aos retornos: não. return, nenhum valor retornado.

const feedCat = (status) => {
if (status === 'hungry') {
return 'Feed the cat';
} else {
return 'Do not feed the cat';
}
};

Tenha cuidado ao retornar literais de objetos de funções de seta, pois as chaves do objeto podem ser confundidas com o corpo da função. Para evitar essa ambiguidade, envolva o objeto literal entre parênteses para que o JavaScript saiba que se trata de uma expressão a ser retornada:

const toObject = value => ({ result: value });

Mais uma coisa: funções de seta são sempre expressões, nunca declarações. Isso significa que eles devem ser atribuídos a uma variável, propriedade ou passados ​​como argumento; eles não podem ficar sozinhos, como function myFunc() {}E elas não são elevadas da mesma forma que as declarações de função, portanto você não pode chamá-las antes de serem definidas.

O que exatamente é this Em JavaScript?

A palavra-chave this É uma ligação dinâmica que o JavaScript cria para você quando executa uma função ou um método de classe. Você pode pensar nisso como um parâmetro invisível cujo valor depende de como e onde a função é chamada. Isso a torna poderosa e flexível, mas também uma grande fonte de confusão.

Em uma função não estrita, this sempre se resolve para algum tipo de objeto; no modo estrito, pode ser literalmente qualquer valor, incluindo undefined. O JavaScript decide esse valor com base no contexto de execução: função regular, chamada de método, chamada de construtor, classe, escopo global ou função de seta.

No nível superior de um script clássico (não um módulo), this refere-se a globalThis, que geralmente é o navegador window objeto. Portanto, a seguinte comparação em um navegador será verdadeira:

console.log(this === window); // true

Em funções que não são setas, this é determinado inteiramente pelo local da chamada. Se você ligar obj.method(), então dentro method o valor de this is objSe você pegar essa mesma função e chamá-la de forma independente como fn() Em modo estrito, this torna-se undefined; no modo não estrito, o JavaScript “substitui” this com globalThis.

É importante ressaltar que o que importa não é onde a função é definida, mas como ela é chamada. Um método pode existir na cadeia de protótipos ou ser reatribuído a um objeto diferente e ainda assim ser visível. this como qualquer objeto que seja realmente usado no momento da chamada. Passar um método adiante geralmente altera seu objeto. this a menos que você corrija isso explicitamente.

Existem também ferramentas para controlar this explicitamente: call, apply, bind e Reflect.apply. Esses dispositivos permitem "injetar" o desejado. this valor: fn.call(obj, arg1, arg2) irá executar fn com this definido para objAs mesmas regras de substituição se aplicam no modo não estrito: se você passar null or undefined as this, eles são substituídos por globalThisOs tipos primitivos são encapsulados em seus objetos de encapsulamento.

Os callbacks adicionam outra camada de indireção, porque this é controlado por quem liga para o seu retorno de chamada. Métodos de iteração de arrays, o Promise construtores e APIs semelhantes geralmente chamam funções de retorno de chamada com this definido para undefined (ou o objeto global no modo desleixado). Algumas APIs, como Array.prototype.forEach or Set.prototype.forEach, aceitar um separado thisArg parâmetro que você pode usar para definir o retorno de chamada this.

Outras APIs chamam intencionalmente funções de retorno de chamada com parâmetros personalizados. this valores. Por exemplo, a reviver argumento para JSON.parse e replacer for JSON.stringify receber this Os manipuladores de eventos no DOM estão vinculados ao objeto que possui a propriedade que está sendo processada. Quando escritos da maneira "clássica", os manipuladores de eventos no DOM estão vinculados ao elemento ao qual estão anexados.

A ideia central: as funções de seta não criam suas próprias funções de seta. this

A característica definidora das funções de seta é que elas nunca criam uma nova função. this obrigatório. Em vez disso, eles se fecham sobre (ou “capturam”) o this do ambiente léxico circundante no momento em que são criados. Quando a seta é executada posteriormente, ela simplesmente reutiliza esse valor capturado, independentemente de como você o chama.

Na prática, uma função de seta se comporta como se estivesse permanentemente vinculada automaticamente ao this do seu âmbito exterior. É por isso que métodos como call, apply e bind não pode mudar this para uma função de seta: a thisArg O argumento é simplesmente ignorado. Você ainda pode passar parâmetros regulares por meio deles, mas o this O valor está bloqueado.

Considere este trecho de código no escopo global de um arquivo de script:

const arrow = () => console.log(this);
arrow();

Como a seta é definida no código global, seu this é o global this (tipicamente window em um script de navegador), e isso nunca muda. chamada arrow Como uma função simples, atribuí-la a uma propriedade ou passá-la como argumento sempre registrará o mesmo objeto global quando invocada neste contexto.

O comportamento realmente interessante surge quando você aninha funções de seta dentro de funções ou métodos regulares. Como a seta captura a função externa this, torna-se uma ferramenta poderosa para callbacks que precisam se referir ao objeto que os contém sem o usual .bind(this) cerimônia.

const counter = {
id: 42,
start() {
setTimeout(() => {
console.log(this.id); // uses counter.id
}, 1000);
},
};

If start estavam usando uma função anônima tradicional dentro setTimeoutvocê precisaria vincular manualmente this ou salve-o em uma variável. Com setas, o retorno de chamada herda naturalmente o this da start, o que é counter, assim this.id impressões 42 como pretendido.

Essa ligação lexical também explica a clássica pergunta “por que será que...”. this A questão da "alteração" surge ao usar setas em literais de objeto. Observe estes dois objetos:

const obj1 = {
speak() {
console.log(this);
}
};

const obj2 = {
speak: () => {
console.log(this);
}
};

chamada obj1.speak() impressões obj1, Porque speak é um método regular e this é definido com base no local da chamada. Em contraste, obj2.speak() registros do exterior this (frequentemente window (em navegadores), porque a seta não usa o objeto como seu thisO próprio objeto literal não cria um novo objeto. this escopo; somente o corpo da função faz isso, e as funções de seta pulam essa etapa.

Agora considere um método de objeto que cria e chama imediatamente uma seta interna:

const obj3 = {
speak() {
(() => {
console.log(this);
})();
}
};

obj3.speak();

Nessa situação, a função de seta interna herda this da speak, o que é obj3 quando chamado como obj3.speak(). Embora a seta seja uma função aninhada, invocada imediatamente, ela ainda aponta para obj3, não o objeto global. Essa é a essência do léxico. this: segue o escopo circundante, não o local de impacto da própria seta.

this em funções, objetos e construtores

Para realmente dominar as funções de seta e this, ajuda ver como this Funciona em todos os principais contextos: funções regulares, métodos, construtores, classes e escopo global. Uma vez que essas regras estejam claras, o comportamento das setas torna-se muito mais fácil de entender.

Em uma função simples (não-seta), this Depende 100% de como a função é invocada. Se você ligar fn() Em modo estrito, this is undefined; no modo desleixado, a substituição faz this tornam-se globalThisSe você ligar obj.fn(), Em seguida this is obj. Mover fn para um objeto diferente ou para uma variável e o valor de this agiremos de acordo.

Em um método definido em um objeto literal, this é o objeto no qual o método é acessado, e não necessariamente aquele onde o método foi originalmente definido. If obj.__proto__ contém um método e você o chama. obj.method(), então dentro method, this is obj, não o protótipo.

Construtores são outro caso especial: quando você chama uma função com new, this está vinculado à instância do objeto recém-criada. Por exemplo, em function User(name) { this.name = name; }chamando new User('Alex') conjuntos this para o novo User objeto. Se o construtor retornar explicitamente um objeto não primitivo, esse objeto retornado substitui this como o valor final do new expressão.

A sintaxe de classe se baseia nessas regras com dois contextos principais: instância e estático. Dentro de um construtor ou de um método de instância, this aponta para a instância da classe com a qual você está trabalhando. Dentro de métodos estáticos ou blocos de inicialização estática, this refere-se à própria classe (ou à classe derivada quando chamada por herança). Os campos de instância são avaliados com this vinculado à nova instância; veja campos estáticos this como o construtor da classe.

Os construtores de classes derivadas se comportam de maneira ligeiramente diferente: até que você chame super(), não há nada utilizável this. Invocando super() inicializa this Ao delegar para o construtor da classe base; retornar antes de fazer isso em um construtor derivado só é permitido se você retornar explicitamente um objeto diferente.

No contexto global, this Depende de como o ambiente JavaScript encapsula e executa seu código. Em um script de navegador clássico, nível superior this é o objeto global; em um módulo ES, nível superior this é sempre undefinedOs módulos CommonJS do Node.js são encapsulados internamente e geralmente são executados com this definido para module.exportsOs atributos de manipulador de eventos embutidos no HTML são executados com this definidos para o elemento ao qual estão anexados.

Um detalhe sutil, porém importante: os literais de objeto em si não introduzem um novo this escopo. Conteúdos const obj = { value: this }; dentro de um script fará obj.value igual ao exterior this, não o objeto. Somente os corpos de funções (e corpos de classes) criam um dedicado this vinculação; as setas intencionalmente ignoram esta etapa e herdam o processo.

Por que as funções de seta são ótimas para callbacks (e quando não são)

Porque as funções de seta se fecham sobre thisEles são perfeitos para muitos cenários de retorno de chamada em que você deseja que o retorno de chamada continue se referindo ao objeto ou contexto circundante. Isso é particularmente útil com temporizadores, promessas e métodos de matriz como map, filter e reduce.

Imagine um método que precisa atualizar alguma propriedade repetidamente usando setInterval. Utilizando uma função tradicional, this dentro do callback, o padrão seria o objeto global (ou seria undefined (no modo estrito), então this.count não apontaria para sua instância. Com uma função de seta, o retorno de chamada usa naturalmente o this do método externo.

function Counter() {
this.count = 0;

setInterval(() => {
this.count++;
}, 1000);
}

Graças à seta, this dentro do retorno de chamada do intervalo refere-se a Counter instância, não window. Se esse retorno de chamada fosse uma função normal, você precisaria... .bind(this) ou uma variável intermediária como const self = this; para manter a referência.

As funções de seta também simplificam o código que usa métodos de array, onde você geralmente não precisa se preocupar com... this de todo. Quando você passa uma função tradicional como retorno de chamada, o implícito this é geralmente undefinedE você pode se esquecer disso. As setas tornam visualmente óbvio que a função é apenas um mapeamento puro de entradas para saídas.

const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);

No entanto, existem casos importantes em que as funções de seta são a escolha errada, particularmente quando você precisa de uma função dinâmica. this. Dois antipadrões clássicos são o uso de funções de seta como métodos de objeto e como manipuladores de eventos DOM que dependem de this sendo o elemento.

Considere um objeto que rastreia a vida de um gato:

const cat = {
lives: 9,
jump: () => {
this.lives--; // bug: this is not cat
},
};

cat.jump();

Como jump é uma flecha, this não se refere a cat mas seja lá o que for this era onde o objeto literal era criado (geralmente o objeto global). O pretendido this.lives-- Ou lança uma exceção (no modo estrito) ou modifica silenciosamente algo não relacionado. Usar a sintaxe de método regular aqui é a abordagem correta.

Os ouvintes de eventos DOM são semelhantes: o padrão padrão this.classList.toggle('on') dentro de um retorno de chamada de evento depende de this sendo o elemento que desencadeou o evento. Com uma função de seta, this não aponta mais para o elemento, então o código para de funcionar.

const button = document.getElementById('press');

button.addEventListener('click', () => {
this.classList.toggle('on'); // this is not button
});

Nessa situação, o manipulador deve ser uma função normal para que this está vinculado pelo navegador ao elemento botão. As funções de seta simplesmente não funcionam como substitutas diretas se a sua lógica espera this Ser o alvo dinâmico do evento.

Outra desvantagem sutil é que as funções de seta são sintaticamente anônimas. Geralmente, elas não possuem um nome próprio (além da variável à qual são atribuídas), o que pode tornar os rastreamentos de pilha um pouco menos descritivos e a recursão um pouco mais complexa. Na maioria dos códigos do mundo real, essa é uma compensação aceitável, mas vale a pena lembrar.

Casos especiais: getters, setters, métodos vinculados e situações atípicas.

Os jogadores que recebem a bola (getters) e os que a levantam (setters) seguem a mesma regra de "local de chamada": this é o objeto no qual a propriedade é acessada, não aquele em que ela foi originalmente definida. Se um getter for herdado de um protótipo e você o chamar em um objeto derivado, this O método getter se refere ao objeto derivado.

Métodos vinculados criados com Function.prototype.bind Oferecem um comportamento um tanto semelhante ao das funções de seta, mas no nível das funções normais. Quando Você ligar f.bind(obj), você cria uma nova função cujo this está permanentemente fixado em obj, independentemente de como for invocado. Isso pode ser útil em classes quando você precisa preservar this mesmo que um método esteja desanexado.

class Example {
constructor() {
this.handleClick = this.handleClick.bind(this);
}

handleClick() {
console.log(this); // always the instance
}
}

A desvantagem de usar métodos vinculados e funções de seta como campos de instância é que cada instância recebe sua própria cópia da função, o que pode aumentar o uso de memória. Essa compensação geralmente é aceitável quando você vincula apenas um pequeno número de métodos frequentemente desanexados, mas é algo a se ter em mente em código crítico para o desempenho.

Existem também alguns casos extremos legados em que this comporta-se de maneira diferente, como em um estado obsoleto. with declaração. Dentro de um with (obj) { ... } bloco, chamando uma função que é uma propriedade de obj comporta-se efetivamente como se você tivesse escrito obj.method(), assim this é obrigado a objO código moderno deve evitar with, mas compreender essa exceção esclarece que this Ainda depende fundamentalmente de como uma chamada de função é formada.

Os manipuladores de eventos embutidos em HTML também têm uma regra especial: o código do manipulador embutido circundante vê this como o elemento, mas as funções internas definidas dentro desse manipulador recorrem ao regular. this regras. Assim, uma função tradicional interna, não vinculada a nada, geralmente verá this as globalThis (ou undefined (no modo estrito), não o elemento.

Por fim, lembre-se de que as funções de seta não têm um prototype propriedade e não podem ser usados ​​como construtores com new. Tentativa new MyArrow() irá gerar um TypeError. Se você precisa de uma função que possa atuar como um construtor, você deve usar uma função regular ou uma classe.

Levar esses detalhes em consideração torna muito mais fácil escolher entre funções de seta e funções tradicionais. Use setas onde você quiser indicar informações lexicais. this sintaxe concisa e recurso a funções regulares sempre que precisar de uma abordagem dinâmica, orientada pelo ponto de chamada. this comportamento ou semântica do construtor.

Uma vez que você internaliza como this Em cada situação, as funções de seta se tornam uma poderosa aliada em vez de uma fonte inesperada de erros. Elas simplificam padrões comuns, como callbacks e transformações simples, enquanto as funções regulares continuam a lidar com tarefas que dependem delas mesmas. this vinculação, como métodos, construtores e manipuladores de eventos dinâmicos.

Artigos relacionados: