Inspirado no CoffeeScript, a versão 6 do ECMAScript nos traz um jeito mais simples e elegante de definirmos funções, as chamadas arrow functions. Não só syntatic sugar, elas vêm para resolver (de forma elegante) o problema do this
dinâmico que todos já enfrentamos ao passarmos funções como callback.
this léxico
No JavaScript o valor do this
é setado dinamicamente em tempo de execução. Ele sempre faz referência ao objeto o qual a função atual é um método. Em outras palavras, ele faz referência ao objeto dono da função. Caso a função não pertença a nenhum objeto (não seja método de nenhum objeto) ele aponta para o objeto global — window
no caso dos navegadores.
Nas funções passadas como callback, o valor do this
é igual ao da window
, uma vez que estamos passando uma função como argumento e nenhum objeto a possui. No strict mode o this
é igual a undefined
dentro de uma função passada como callback.
var armazem = {
estabelecimentoNome: 'Armazém do Chico',
logVendaDeCerveja: function(cervejas) {
// não gera erro
console.log(this.estabelecimentoNome.toUpperCase() + '\n\n');
cervejas.forEach(function(cerveja) {
// gera erro, `this` aponta para `window`
console.log(this.estabelecimentoNome + ' vendeu ' + cerveja);
});
}
}
armazem.logVendaDeCerveja(cervejas);
No exemplo acima um erro é gerado, uma vez que this
aponta para window
e não para objeto armazem
, como é esperado. Temos alguns jeitos de contornar isso, claro. Mas não vamos entrar em detalhes sobre isso agora.
As arrow functions vêm solucionar principalmante esse tipo de cenário. Com elas, o valor do this
deixa de ser dinâmico e passa a ser estático. O que as tornam perfeitas para uso em callbacks. O exemplo acima poderia ser reescrito da seguinte forma:
var armazem = {
estabelecimentoNome: 'Armazém do Chico',
logVendaDeCerveja: function(cervejas) {
console.log(this.estabelecimentoNome.toUpperCase() + '\n\n');
cervejas.forEach(cerveja => {
console.log(this.estabelecimentoNome + ' vendeu ' + cerveja);
});
}
}
armazem.logVendaDeCerveja(cervejas);
Agora o valor do this
está setado estaticamente como sendo uma referência ao objeto armazem
. Ou, o valor do this
foi setado como um this
léxico, e não mais dinâmico.
Sintaxe menos verbosa
Havia uma dúvida entre qual tipo de seta usar para as arrow functions. A seta “magra” (->
) ou a seta “gorda” (=>
). No final, a seta “gorda” (fat arrow) acabou se tornando o padrão para se tornar compatível com CoffeeScript, que já possui fat arrow e se comporta de uma maneira similar à proposta do ECMAScript 6.
let soma = (a, b) => {
return a + b
}
Para definirmos argumentos, existem 3 maneiras possíveis. Sem argumentos, um argumento e vários argumentos.
() => { ... } // sem argumentos
a => { ... } // um argumento
(a, b) => { ... } // vários argumentos
Na especificação do corpo da função, podemos definir como um bloco (a forma padrão) ou como uma expressão que é retornada implicitamente.
a => { return 2 * a } // bloco
a => 2 * a // expressão, equivalente à linha anterior
Por baixo dos panos, as arrow functions são apenas syntatic sugar para o método Function.prototype.bind
.
Não podem ser usadas como construtores
Usar new
com arrow functions não é possível, pois elas não possuem o método interno [[Construct]] (o que permite que uma função normal seja usada com new
) e muito menos a propriedade prototype
. E já que seu this é léxico, e não dinâmico, não faria o mínimo sentido de qualquer forma.
var foo = new () => {}; // gera um erro
Suporte | |||||
---|---|---|---|---|---|
arrow function | -- | -- | 22.0 | -- | -- |
Por ser uma nova feature do também novo ECMAScript 6.0, apenas um browser, o Firefox 22.0, dá suporte.