Arrow functions
Esta aula aborda as arrow functions do JavaScript, explicando sua sintaxe concisa, como o escopo do 'this' difere das funções tradicionais e em quais situações é recomendado evitar seu uso.
As arrow functions, introduzidas no ES6 (ECMAScript 2015), são uma forma mais concisa de escrever funções em JavaScript. Elas oferecem uma sintaxe enxuta e um comportamento diferenciado para o valor de this, o que as torna muito úteis em certos cenários, mas também exige cuidado em outros.
Nesta aula, vamos explorar a sintaxe curta das arrow functions, entender como o this é tratado de forma léxica (baseada no contexto de definição) e aprender quando é melhor optar por funções tradicionais.
Sintaxe curta
A principal característica das arrow functions é sua sintaxe reduzida. Enquanto uma função tradicional usa a palavra-chave function, a arrow function utiliza a seta =>. A forma básica é:
const funcao = (parametros) => { corpo };Se a função tiver apenas um parâmetro, os parênteses podem ser omitidos:
const quadrado = x => { return x * x; };Se o corpo da função for uma única expressão, as chaves e a palavra return podem ser omitidas, resultando em um retorno implícito:
const quadrado = x => x * x;Para funções sem parâmetros ou com dois ou mais parâmetros, os parênteses são obrigatórios:
const saudacao = () => "Olá!";
const soma = (a, b) => a + b;Quando o corpo da função retorna um objeto literal, é necessário envolvê-lo entre parênteses para evitar ambiguidade com o bloco de código:
const criarPessoa = (nome, idade) => ({ nome: nome, idade: idade });Diferenças no this
Em funções tradicionais, o valor de this é determinado pelo contexto de chamada (quem invoca a função). Já nas arrow functions, this é herdado do escopo léxico (o escopo onde a função foi definida), ou seja, ele não é redefinido pela chamada.
Isso é particularmente útil em callbacks e métodos de objetos, onde queremos manter o contexto original. Por exemplo:
function Contador() {
this.valor = 0;
setInterval(() => {
this.valor++;
console.log(this.valor);
}, 1000);
}
new Contador();Neste caso, a arrow function dentro de setInterval captura o this do escopo da função Contador, que é a instância do objeto. Se usássemos uma função tradicional, this seria o objeto global (ou undefined em strict mode), causando um erro.
Outro exemplo comum é em métodos de array como map, filter e reduce:
const numeros = [1, 2, 3];
const dobrados = numeros.map(n => n * 2);
console.log(dobrados); // [2, 4, 6]Aqui, a arrow function é perfeita porque não precisa de seu próprio this.
Quando NÃO usar
Apesar das vantagens, há situações em que arrow functions não são adequadas:
- Métodos de objetos: Se você usar uma arrow function como método de um objeto, o
thisnão se referirá ao objeto, mas ao escopo externo (geralmente o escopo global ou de uma função pai). - Construtores: Arrow functions não podem ser usadas como construtoras com
new. Elas não possuem a propriedadeprototypee lançam um erro se tentarmos instanciá-las. - Métodos que precisam de
arguments: Arrow functions não possuem o objetoargumentspróprio. Se precisar acessar os argumentos de forma dinâmica, use uma função tradicional ou o operador rest (...args). - Event handlers do DOM que precisam de
thisreferindo ao elemento: Em manipuladores de eventos, se você precisa quethisseja o elemento alvo, use uma função tradicional. Com arrow function,thisserá o escopo externo.
Exemplo de erro ao usar arrow function em método de objeto:
const obj = {
nome: "Exemplo",
saudacao: () => {
console.log("Olá, " + this.nome); // this não é obj
}
};
obj.saudacao(); // "Olá, undefined"Para esses casos, prefira funções tradicionais:
const obj = {
nome: "Exemplo",
saudacao: function() {
console.log("Olá, " + this.nome);
}
};
obj.saudacao(); // "Olá, Exemplo"Boas práticas
- Use arrow functions para funções curtas e que não precisam de seu próprio
this, especialmente em callbacks e métodos de array. - Evite arrow functions em métodos de objetos, construtores e funções que usam
arguments. - Para legibilidade, mantenha a sintaxe consistente: se a função for simples, use a forma concisa; se tiver múltiplas linhas, use chaves e
returnexplícito.
Referências
- MDN: Arrow functions
- MDN: this
- JavaScript.info: Arrow functions
- W3Schools: Arrow Function
- freeCodeCamp: When (and why) you should use arrow functions
Exercícios
- Converta a função tradicional abaixo em uma arrow function com retorno implícito (uma linha):
function soma(a, b) { return a + b; } - Escreva uma arrow function que receba um número e retorne seu quadrado, usando retorno implícito.
- Explique por que o código a seguir imprime "undefined" e corrija-o usando uma função tradicional:
const pessoa = { nome: "João", falar: () => { console.log("Meu nome é " + this.nome); } }; pessoa.falar(); - Dado o array
const numeros = [1, 2, 3, 4, 5];, use uma arrow function comfilterpara obter apenas os números pares. - Tente executar
new (() => {})no console do navegador ou Node.js. O que acontece? Por quê?
const soma = (a, b) => a + b;const quadrado = x => x * x;this; ele é herdado do escopo global (ou undefined em strict mode). Para corrigir, use uma função tradicional:const pessoa = {
nome: "João",
falar: function() {
console.log("Meu nome é " + this.nome);
}
};
pessoa.falar(); // "Meu nome é João"const pares = numeros.filter(n => n % 2 === 0);
console.log(pares); // [2, 4]TypeError: (intermediate value) is not a constructor. Isso ocorre porque arrow functions não têm a propriedade prototype e não podem ser usadas como construtoras com new.