Arrow functions
BaselineWidely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2016.
Umaexpressãoarrow function possui uma sintaxe mais curta quando comparada a uma expressão de função (function expression) e não tem seu própriothis,arguments,super ounew.target. Estas expressões de funções são melhor aplicadas para funções que não sejam métodos, e elas não podem ser usadas como construtores (constructors).
Experimente
const materials = ["Hydrogen", "Helium", "Lithium", "Beryllium"];console.log(materials.map((material) => material.length));// Expected output: Array [8, 6, 7, 9]
Sintaxe
Sintaxe básica
(param1, param2, …, paramN) => { statements }(param1, param2, …, paramN) => expression// equivalente a: => { return expression; }// Parênteses são opcionais quando só há um nome de parâmetro:(singleParam) => { statements }singleParam => { statements }// A lista de parâmetros para uma função sem parâmetros deve ser escrita com um par de parênteses.() => { statements }
Sintaxe avançada
// Envolva o corpo da função em parênteses para retornar uma expressão literal de objeto:params => ({foo: bar})// Parâmetros rest (rest parameters) e parâmetros padrões (default parameters) são suportados(param1, param2, ...rest) => { statements }(param1 = defaultValue1, param2, …, paramN = defaultValueN) => { statements }// Desestruturação (destructuring) dentro da lista de parâmetros também é suportadovar f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;f(); // 6
Descrição
Veja também"ES6 In Depth: Arrow functions" on hacks.mozilla.org.
Dois fatores influenciaram a introdução dasarrow functions: funções mais curtas e a inexistência da palavra chavethis
.
Funções mais curtas
var elements = [ 'Hydrogen', 'Helium', 'Lithium', 'Beryllium'];elements.map(function(element) { return element.length;}); // esta sentença retorna o array: [8, 6, 7, 9]// A função regular acima pode ser escrita como a arrow function abaixoelements.map((element) => { return element.length;}); // [8, 6, 7, 9]// Quando só existe um parâmetro, podemos remover os parênteses envolvendo os parâmetros:elements.map(element => { return element.length;}); // [8, 6, 7, 9]// Quando a única sentença em uma arrow function é `return`, podemos remover `return` e remover// as chaves envolvendo a sentençaelements.map(element => element.length); // [8, 6, 7, 9]// Neste caso, porque só precisamos da propriedade length, podemos usar o parâmetro de destruição (destructing parameter):// Note que a string `"length"` corresponde a propriedade que queremos obter enquanto que a// obviamente propriedade não especial `lengthFooBArX` é só o nome de uma variável que pode ser mudado// para qualquer nome válido de variável que você quiserelements.map(({ "length": lengthFooBArX }) => lengthFooBArX); // [8, 6, 7, 9]// Esta atribuição de parâmetro de destruição (destructing parameter) pode ser escrita como visto abaixo. Entretanto, note que// não há um específico `"length"` para selecionar qual propriedade nós queremos obter. Ao invés disso, o nome literal// da própria variável `length` é usado como a propriedade que queremos recuperar do objeto.elements.map(({ length }) => length); // [8, 6, 7, 9]
Semthis
separado
Antes dasarrow functions, toda nova função definia seu próprio valor dethis (baseado em como a função era chamada, um novo objeto no caso de um construtor,undefined em chamadas de funções com modo estrito (strict mode), o objeto base se a função é chamada como um "método de objeto", etc.). Este comportamento é importuno com um estilo de programação orientado a objeto.
function Person() { // O contrutor Person() define `this` como uma instância dele mesmo. this.age = 0; setInterval(function growUp() { // Em modo não estrito, a função growUp() define `this` // como o objeto global (porque é onde growUp() é executado.), // que é diferente ao `this` // definido pelo construtor Person(). this.age++; }, 1000);}var p = new Person();
No ECMAScript 3/5, este comportamento era corrigido definindo o valor emthis
à uma variável que pudesse ser encapsulada.
function Person() { var that = this; that.age = 0; setInterval(function growUp() { // A chamada a função refere à variáevel `that` da qual // o valor é o objeto esperado. that.age++; }, 1000);}
Alternativamente, uma função de ligação (bound function) pode ser criada para que o valor pré-atribuido àthis
seja passado para a função alvo de ligação (a funçãogrowUp()
no exemplo acima.
Umaarrow function não tem seu própriothis;
o valorthis
do contexto léxico encapsulado é usado. Ex:Arrow functions seguem as regras normais de pesquisa de variáveis. Então, ao procurar porthis
, que não está no escopo atual elas acabam encontrandothis
no escopo encapsulado. Assim, no código a seguir, othis
dentro da função que é passado parasetInterval
tem o mesmo valor dothis
na função lexicamente encapsulada:
function Person() { this.age = 0; setInterval(() => { this.age++; // |this| corretamente se refere ao objeto Person }, 1000);}var p = new Person();
Relação comstrict mode
Considerando quethis
vem do contexto léxico envolvente, as regras do modo estrito (strict mode) em relação aothis
são ignoradas.
var f = () => { "use strict"; return this;};f() === window; // ou o objeto global
O restante das regras do modo estrito (strict mode) são aplicadas normalmente.
Invocação por call ou apply
Já que asarrow functions não têm o própriothis
, os métodoscall()
ouapply()
só podem passar parâmetros.thisArg
é ignorado.
var adder = { base: 1, add: function(a) { var f = v => v + this.base; return f(a); }, addThruCall: function(a) { var f = v => v + this.base; var b = { base: 2 }; return f.call(b, a); }};console.log(adder.add(1)); // Deve logar 2console.log(adder.addThruCall(1)); // Deve logar 2 ainda
Sem ligação (binding) de argumentos (arguments
)
Arrow functions não tem o próprio objeto argumentos (arguments object). Assim, neste exemplo,arguments
é simplesmente uma referência aos argumentos do escopo encapsulado:
var arguments = [1, 2, 3];var arr = () => arguments[0];arr(); // 1function foo(n) { var f = () => arguments[0] + n; // ligação implícita dos argumentos de foo. arguments[0] é n return f();}foo(3); // 6
Na maioria dos casos, usar parâmetros rest (rest parameters) é uma boa alternativa a usar um objetoarguments
.
function foo(n) { var f = (...args) => args[0] + n; return f(10);}foo(1); // 11
Arrow functions usadas como métodos
Como afirmado anteriormente, expressõesarrow function são melhores para funções que não sejam métods. Vamos ver o que acontece quando tentamos usá-las como métodos.
'use strict';var obj = { i: 10, b: () => console.log(this.i, this), c: function() { console.log(this.i, this); }}obj.b(); // imprime undefined, Window {...} (ou o objeto global)obj.c(); // imprime 10, Object {...}
Arrow functions não tem o própriothis
. Outro exemplo envolvendoObject.defineProperty()
:
'use strict';var obj = { a: 10};Object.defineProperty(obj, 'b', { get: () => { console.log(this.a, typeof this.a, this); // undefined 'undefined' Window {...} (ou o objeto global) return this.a + 10; // representa o objeto global 'Window', portanto 'this.a' retorna 'undefined' }});
Uso do operadornew
Arrow functions não podem ser usadas como construtores e lançarão um erro quando usadas com onew
.
Uso da propriedadeprototype
Arrow functions não têm a propriedadeprototype
.
var Foo = () => {};console.log(Foo.prototype); // undefined
Uso da palavra chaveyield
A palavra chaveyield
não pode ser usada no corpo de umaarrow function (exceto quando permitido dentro de funções aninhadas dentro delas). como consequência,arrow functions não podem ser usadas como geradoras (generators).
Corpo de função
Arrow functions podem ter um corpo conciso ("concise body") ou o usual corpo em bloco ("block body").
Em umconcise body, apenas uma expressão é especificada, a qual se torna o valor de retorno implícito. Em umblock body, você precisa explicitamente usar a declaração de retorno, ou seja, oreturn
.
var func = x => x * x;// sintaxe de concise body. O "return" é implícitovar func = (x, y) => { return x + y; };// Em um função com block body, é necessário um "return" explícito
Retornando objetos literais
Tenha em mente que retornar objetos literais usando a sintaxe de corpo conciso (concise body)params => {object:literal}
não funcionará como esperado.
var func = () => { foo: 1 };// Chamar func() retornará undefined!var func = () => { foo: function() {} };// SyntaxError (Erro de sintaxe): a declaração da função requer um nome
Isto acontece porque o código dentro das chaves ({}) é convertido como uma sequência de sentenças (ex:foo
é tratado como um título, não como uma chave num objeto literal).
Se lembre de envolver o objeto literal em parênteses.
var func = () => ({foo: 1});
Quebras de linha
Umaarrow function não pode conter uma quebra de linha entre seus parâmetros e sua flecha.
var func = (a, b, c) => 1;// SyntaxError (Erro de sintaxe): esperada expressão, mas obteve '=>'
Entretanto, isto pode ser corrigido ao usar parênteses ou colocar a quebra de linha dentro dos argumentos como visto abaixo para garantir que o código permaneça bonito e leve.
var func = (a, b, c) => 1;// SyntaxError (erro de sintaxe) não é lançado
Ordem de análise
Apesar de a flecha numaarrow function não ser um operador,arrow functions possuem regras especiais de análise que interagem diferentemente com precedência de operador (operator precedence) comparadas à funções comuns.
let callback;callback = callback || function() {}; // okcallback = callback || () => {};// SyntaxError (Erro de sintaxe): argumentos inválidos de arrow-functioncallback = callback || (() => {}); // ok
Mais exemplos
// Uma arrow function vazia retorna undefinedlet empty = () => {};(() => 'foobar')();// Retorna "foobar"// (esta é uma Expressão de Função Invocada Imediatamente (Immediately Invoked Function Expression)// veja 'IIFE' no glossário)var simple = a => a > 15 ? 15 : a;simple(16); // 15simple(10); // 10let max = (a, b) => a > b ? a : b;// Mapeamento, filtragem, ... simples de arrayvar arr = [5, 6, 13, 0, 1, 18, 23];var sum = arr.reduce((a, b) => a + b);// 66var even = arr.filter(v => v % 2 == 0);// [6, 0, 18]var double = arr.map(v => v * 2);// [10, 12, 26, 0, 2, 36, 46]// Cadeias de promessa (promisse chains) mais concisaspromise.then(a => { // ...}).then(b => { // ...});// Arrow functions sem parâmetros que são visualmente mais fáceis de analisarsetTimeout( () => { console.log('E aconteço antes'); setTimeout( () => { // deeper code console.log('Eu aconteço depois'); }, 1);}, 1);
Especificações
Specification |
---|
ECMAScript® 2026 Language Specification # sec-arrow-function-definitions |