ECMAScript 6 Arrow Function

ECMAScript 6 Arrow Function

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.

#51