Allysson Santos

Front-end Developer

Arrow Functions

Introdução:

Veja como funcionam as arrows functions introduzidas no ES6! Entenda sua sintaxe e como se comporta o valor de this.

Arrow Functions
Nível: iniciante

Introdução

Arrow function é uma nova forma de se escrever funções anonimas, vamos entender sua sintaxe e como funciona o seu valor de this.

Sintaxe

Uma função anonima no ES5 era assim:

1
2
3
4
5
6
var paises = ['Alemanha', 'Estados Unidos'];
var irei = paises.map(function(pais) {
  return 'Um dia irei para ' + pais;
});
console.log(irei);
> ["Um dia irei para Alemanha", "Um dia irei para Estados Unidos"]

Com as arrows functions, podemos simplifica-las das seguintes formas:

1
2
3
4
5
6
7
8
9
10
11
12
var paises = ['Alemanha', 'Estados Unidos'];
const ireiSemFunction = paises.map((pais) => {
  return 'Um dia irei para ' + pais;
}); // Podemos tirar a palavra function e adicionar uma => a frente dos () dos parametros.

const ireiComUmParametro = paises.map(pais => {
  return 'Um dia irei para ' + pais;
}); // Caso a função tenha apenas um parâmetro, podemos retirar o seus parênteses.

const ireiEmUmaLinha = paises.map(pais => 'Um dia irei para ' + pais);
/* Caso a função tenha apenas um parâmetro e retorne logo na primeira linha,
podemos escrever sem as chaves e sem a palavra return */

Recapitulando:

  • Podemos tirar a palavra function e adicionar uma seta => em frente os parênteses dos parâmetros.
  • Se a sua função anonima tiver apenas um parâmetro, pode retirar seus parênteses.
  • Se a função não tiver parâmetros, podemos deixar () vazio mesmo.
  • Se a função der um return na primeira linha, podemos escrever apenas em uma linha, sem chaves e sem a palavra return.

Objeto this

O this dentro de uma arrow function se comporta de uma maneira diferente da que estamos acostumados, primeiro, vamos analisar um código javascript sem uso de arrow functions.

Imagine que temos o seguinte HTML e JS:

1
2
3
4
5
6
7
8
9
10
11
12
<html>
<body>
  <button id="btn">Click!</button>
</body>
<script>
  var btn = document.getElementById('btn');

  btn.addEventListener('click', function () {
    console.log(this)
  });
</script>
</html>

Na função acima, ao clicar no botão com id='btn' iremos logar o valor de this, que nesse caso é o próprio botão. Teremos como saída essa resposta:

1
<button id="btn">Click</button>

Se esse mesmo código for escrito com arrow function o resultado não será o mesmo, pois o valor de this não está referenciado ao botão que está acontecendo a ação, ele está referenciado a todo o contexto que a função está inserida, no nosso caso, o contexto é a window.

Ao clicar no botão com uma arrow function, teremos o seguinte retorno:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<html>
<body>
  <button id="btn">Click!</button>
</body>
<script>
  var btn = document.getElementById('btn');

  btn.addEventListener('click', () => { // <-- mudança aqui
    console.log(this)
  });
</script>
</html>
--------------------------
> Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage,
 sessionStorage: Storage, webkitStorageInfo: DeprecatedStorageInfo…}

Agora um outro exemplo para tentar fixar melhor, temos a seguinte estrutura sem o uso de arrow functions ainda:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<html>
<body>
  <button id="btn">Click!</button>
</body>
<script>
  var pessoa = {
    nome: 'Allysson',
    idade: '22',

    apresentar: function () {
      return `Meu nome e ${this.nome} e eu tenho ${this.idade} anos`;
    },

    falar: function () {
      var self = this;
      window.setTimeout(function() {
        console.log(self.apresentar());
      }, 500);
    }
  };

  var btn = document.getElementById('btn');

  btn.addEventListener('click', function() {
    pessoa.falar();
  });
</script>
</html>

Repare que na linha 15 precisamos guardar o valor de this na variável self (nesse moemento o valor de this é o próprio objeto pessoa), se usássemos diretamente o this dentro do console.log que está no setTimeout acabaríamos nos referênciando a window, e dentro da window não possuímos a função falar, ela está dentro de pessoa.

Executando esse JS temos o seguinte log no console:

1
> Meu nome e Allysson e eu tenho 22 anos

Usando arrow functions

Agora se nós mudarmos a função anonima que está dentro do setTimeout para utilizar arrow function, não precisaremos guardar o valor de this dentro de self, pois como é uma arrow function, o contexto de this já é o objeto pessoa, o escopo se mantém o mesmo!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<html>
<body>
  <button id="btn">Click!</button>
</body>
<script>
  var pessoa = {
    nome: 'Allysson',
    idade: '22',

    apresentar: function () {
      return `Meu nome e ${this.nome} e eu tenho ${this.idade} anos`;
    },

    falar: function () {
      window.setTimeout(() => {
        console.log(this.apresentar());
      }, 500);
    }
  };

  var btn = document.getElementById('btn');

  btn.addEventListener('click', function() {
    pessoa.falar();
  });
</script>
</html>

Temos como retorno o mesmo que na função anterior, mas agora sem precisar do self!

1
> Meu nome e Allysson e eu tenho 22 anos

Conclusão

O valor de this com arrow functions pode gerar grandes dores de cabeça, esteja atento, faça testes, pratique criando funções anonimas convencionais e logue o valor de this, faça essa mesma função utilizando arrow functions e compare o valor de this, saiba que o escopo se mantem o mesmo de onde a arrow function foi criada!

Ela é muito boa para ocasiões como no objeto pessoa, mas não parece ser muito interessante quando queremos adicionar um event listener em algum elemento, pois estariamos alterando o escopo, o contexto. Nosso event listener não teria o efeito desejado.

comments powered by Disqus