Arrow function do JavaScript, feliz e simples?
Tags: javascript, node
Published: 2020-02-20 17:18:04

Quando vi a primeira vez a *arrow function* não fiquei muito feliz, principamente porque eu achava ela muito mais complicada de ler, quero te mostrar que o Marco do passado estava errado e que você pode ser muito feliz com a *arrow function*.

{% youtube 3EkS9-P3cIM %}

Ah! Estou considerando que você já sabe o que é uma *function expression*. Se não sabe, recomendo você dar uma lida sobre ela na MDN (Mozilla Developer Network): [Function Expression na MDN](http://bit.ly/function-expression)

# Como funciona a Arrow function?

A **arrow function** tem uma forma mais simples de escrita do que a *function expression*, por exemplo, se pegarmos a função a seguir que está com *function expression*.

```javascript
function sum(number1, number2) {
  return number1 + number2;
}

console.log(sum(2, 2)); // saída: 4
```

E transformar ela em uma **arrow function**, fica assim:

```javascript
const sum = (number1, number2) => {
  return number1 + number2;
}

console.log(sum(2, 2)); // saída: 4
```

O que conseguimos aprender observando os dois códigos, anteriores? Que a *arrow function* é por padrão uma função anônima, mas conseguimos definir um nome para ela, usando a `const sum` que recebeu a nossa *arrow function*. Isso é realmente importante, você não consegue definir um nome para uma *arrow function* como fazemos na *function expression*, onde informamos o nome da função usando `sum` antes dos parênteses.

**Não tente isso, não funciona!!! Arrow functions são anônimas**
```javascript
sum(number1, number2) => {
  return number1 + number2;
}

console.log(sum(2, 2));

/* Erro que você receberá:
SyntaxError: invalid arrow-function arguments (parentheses around the arrow-function may help)
*/
```

# Outras variações da Arrow Function

A sintaxe que acabamos de ver da *arrow function* (a que funciona 😉), não é a única forma de usar ela, vamos ver outras variações a seguir. 

## Sem return mas retorna

Mesmo sem usar `return` dentro de uma *arrow function* conseguimos retorna a soma, para isso nós precisaremos retirar as duas chaves e `return` da nossa *arrow function*, deixando o código assim:

```javascript
const sum = (number1, number2) => number1 + number2;

console.log(sum(2, 2)); // saída: 4
```

É mais simples! Mas será que é mais legível? Para mim não foi no começo, mas agora que já me acostumei com a *arrow function* está realmente simples e feliz.

## Sem parâmetros

Quando você não tem parâmetro na *arrow function* os parênteses permanecem:

```javascript
() => "CollabCode";
```

Se você quer dar um nome para uma *arrow function* é só criar a `const` como fizemos anteriormente:

```javascript
const comunidade = () => "CollabCode";
```

## Só um parâmetro

Quando você tem apenas um parâmetro os parênteses se tornam opcionais:

```javascript
const double = number => number * 2;
```

Se você gosta muito dos parênteses não tem problema pode usar eles também:

```javascript
const double = (number) => number * 2;
```

## Dois ou mais parâmetros

Quando temos dois ou mais parâmetros em uma *arrow function* o uso dos parênteses se tornam obrigatório:

```javascript
const sum = (number1, number2) => number1 + number2;

console.log(sum(20, 20)); // saída: 40
```

## Arrow function com chaves

Toda vez que você usa as chaves em uma *arrow function* ela perde o poder de retornar algo sem a necessidade de escrever `return`:

```javascript
const sum = (number1, number2) => { number1 + number2 };

console.log(sum(20, 20)); // saída: undefined
```

Então, caso você tenha que usar as chaves na *arrow function* e também retornar algo, é necessário usar `return`, como no código a seguir:

```javascript
const sum = (number1, number2) => { 
  return number1 + number2;
};

console.log(sum(20, 20)); // saída: 40
``` 

## Retornando um JSON sem return

Quando você quer retornar um *[JSON (JavaScript Object Notation)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON)* mas sem usar `return` é necessário você envolver o JSON por parênteses:

```javascript
const getPessoa = () => ({name: 'Gabe', eye: 'blue'});

console.log(getPessoa()); // saída: Object { name: "Gabe", eye: "blue" }
```

## IIFE com arrow function

Quando queremos fechar o escopo de um arquivo, em alguns casos usamos uma função anônima que ela mesmo se executa apenas uma vez, chamamos isso de IIFE (Immediately-invoked function expression). Com a *function expression* podemos criar a IIFE de duas maneiras:

```javascript
(function (){
// Seu código que não vazará o arquivo!!!
}());
```

A segunda forma de gerar a IIFE é bem similar a primeira o que muda são os parênteses `()` no final.
```javascript
(function (){
// Seu código que não vazará o arquivo!!!
})();
```

Você também pode fazer isso usando *arrow function*, mas só tem uma forma de fazer isso:

```javascript
(() => {
// Seu código que não vazará o arquivo!!!
})();
```

**A forma a seguir não funciona**
```javascript
(() => {
// Seu código que não vazará o arquivo!!!
}());

/* Erro que você recebe:
SyntaxError: missing ) in parenthetical
*/
```

## O this é muito mas muito mais simples

O `this` da *arrow function* é muito mais previsível do que o da *function expression*, acredito que essa é a coisa mais feliz dela.

A seguir tem uma *function expression* chamada `Person` (Pessoa) e dentro dela temos `this.age` (`age` é idade) que começa com `0`, a cada 1 segundo ela ficará mais velha. Usamos o método `setInterval` que nós permite executar uma função a cada 1000 milesegundos (você pode mudar os milesegundos), o primeiro parâmentro da `setInterval` é a função que será executada e o segundo parâmetro é o tempo do intervalo.


```javascript
function Person() {
  this.age = 0;

  setInterval(function () {
    this.age = this.age + 1; 
    console.log(this) // O this perde o escopo e referência Window
  }, 1000);
}

const person = new Person();
```

Executando o código acima você receberá uma saída similar no seu console:

```bash
Window about:privatebrowsing
Window about:privatebrowsing
Window about:privatebrowsing
Window about:privatebrowsing
Window about:privatebrowsing
...
```

Se você vem de outras linguagens você achará estranho esse comportamento do `this` no JavaScript, antes de existir a *arrow function* nós resolvimos esse tipo de problema criando uma variável chamada `that` e atribuímos a ela o `this`:

```javascript
function Person() {
  const that = this;
  that.age = 0;

  setInterval(function () {
    that.age = that.age + 1; 
    console.log(that) // O this perde o escopo e referência Window
  }, 1000)
}

const person = new Person();
```

Executando o código com o `that` você terá a seguinte saída no terminal:

```bash
Object { age: 1 }
Object { age: 2 }
Object { age: 3 }
Object { age: 4 }
...
```

Aqui vem o momento feliz da sua vida, com a *arrow function* o comportamento do `this` fica mais previsível e o código muito mais simples, ela tem um `this` léxico, isso significa que o `this` não é alterado de forma dinâmica respeitando o escopo de onde ele foi criado:

```javascript
function Person() {
  this.age = 0;

  setInterval(() => {
    this.age = this.age + 1;
    console.log(this)
  }, 1000)
}

const person = new Person();
```

Execute o código e você terá a seguinte saída:

```bash
Object { age: 1 }
Object { age: 2 }
Object { age: 3 }
Object { age: 4 }
...
```

Se você sentiu falta de algum assunto no post ou discorda de algo que escrevi, não deixe de falar nos comentários, eu gosto muito de feedback, principalmente os negativos que nos fazem evoluir.

Ah! Caso você queira tirar dúvidas de JavaScript cola aí na comunidade CollabCode no Discord: [Link do Discord da CollabCode](http://bit.ly/discord-collabcode)

# Referências de estudo:

- [Arrow function MDN](https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
- [When (and why) you should use ES6 arrow functions — and when you shouldn’t](https://www.freecodecamp.org/news/when-and-why-you-should-use-es6-arrow-functions-and-when-you-shouldnt-3d851d7f0b26/)