Conhecendo Arrow Functions

Felipe Nascimento
Felipe Nascimento

Compartilhe

Imagem de uma mulher na frente de um notebook mexendo com códigos.

Uma escola precisa imprimir uma lista de todos os funcionarios e o código da turma, e para realizar essa ação temos a seguinte classe:


class ModuloDeImpressao {
    constructor() {
        this._codigo = 10;
    }
    imprime(nomes) {
        nomes.forEach(function(nome){
        console.log(`${this._codigo}: ${nome}`);
     });
   }
}

O problema é que após o teste inicial:


const professores = ['Elias', 'Yuri', 'Gabriel', 'Guilherme', 'Yan'];
const impressao = new ModuloDeImpressao();
impressao.imprime(professores);

Está sendo mostrado no console o seguinte erro:

O que vamos fazer é descobrir o porquê e como resolver esse erro.

Entendendo o erro

O JavaScript está nos dizendo que this._codigo é undefined, ou seja, não tem nenhum valor atribuído a ele. Isso ocorre porque o this dentro de uma função tem um comportamento dinâmico, isto é, variando de acordo com o contexto de execução.

No nosso caso, esse erro ocorre porque, no momento de execução do forEach, o contexto do this._codigo é o contexto da função passada para o forEach e não o da classe ModuloDeImpressao que contém o construtor com o código da turma.

Banner promocional da Imersão Cloud DevOps da Alura e Google Cloud com o texto "INSCRIÇÕES ABERTAS PARA A PRIMEIRA EDIÇÃO DA IMERSÃO CLOUD DEVOPS" e a informação de 3 aulas gratuitas com certificado. A imagem mostra um desenvolvedor focado usando fones de ouvido em um computador, com uma colega trabalhando ao fundo, e um botão chamativo com a frase "GARANTA A SUA VAGA".

Contexto

O que queremos dizer com contexto é que, durante a execução do forEach vamos acessar a propriedade onde está o código da turma, porém não vamos conseguir encontrar essa propriedade, porque em nenhum lugar dentro da função que o forEach está executando existe o this._codigo.

Ou seja, fora do contexto do forEach conseguimos acessar a propriedade this._codigo:


class ModuloDeImpressao {
    constructor() {
        this._codigo = 10;
    }
    imprime(nomes) {
        console.log(this._codigo);
        nomes.forEach(function(nome){
        console.log(`${this._codigo}: ${nome}`);
     });
   }
}
const impressao = new ModuloDeImpressao();
impressao.imprime(professores);

Como resultado obtemos:

Após instanciarmos a classe novamente, podemos perceber que conseguimos imprimir o código sem problemas, mas ainda estamos com erro. O que queremos é uma maneira de acessar o contexto da classe ModuloDeImpressao no momento em executarmos o laço forEach.

Arrow Function

A versão do ECMA Script 2015 do JavaScript, trouxe uma nova forma mais sucinta de trabalhar com funções chamada de Arrow Functions, por causa da sintaxe que lembra uma flecha: () =>.

Mas a Arrow Function não é só uma maneira menos verbosa de escrever uma função, ela tem uma característica em particular que vai nos auxiliar em nosso problema: o escopo léxico. Mas como assim o escopo léxico?

Escopo Léxico

Escopo léxico, significa que podemos acessar a propriedade código dentro do nosso forEach. O this não irá variar de acordo com o contexto. Agora, como o contexto do this._codigo é o da classe MóduloDeImpressão temos acesso a propriedade código:


nomes.forEach((nome) => {
    console.log(`${this._codigo}: ${nome}`);
});

Agora que sabemos como funciona othis e a arrow function, vamos aplicar no nosso problema.

Resolvendo o problema

Agora utilizando uma arrow function em nossa classe, temos acesso ao construtor no momento em que entrarmos no laço doforEach, porque o this._codigo vai estar sempre no contexto da classe ModuloDeImpressao.

Depois de aplicar a técnica da arrow function, nosso código ficou assim:


class ModuloDeImpressao {
    constructor() {
        this._codigo = 10;
    }
    imprime(nomes) {
        nomes.forEach(nome => {
        console.log(`${this._codigo}: ${nome}`);
    });
  }
}

Quando instanciamos um novoModuloDeImpressao:


const professores = ['Elias', 'Yuri','Gabriel', 'Guilherme','Yan'];
const impressao = new ModuloDeImpressao();
impressao.imprime(professores);

Temos como resultado no console:

Ótimo, conseguimos resolver nosso problema com relação ao contexto do this! Agora já temos o código da turma e o nome dos professores.

Outra solução

Além das arrow functions, outra maneira que podemos solucionar esse problema é através do método bind, que vai fixar um valor para o this, assim ele não irá variar de acordo com o contexto em que está inserido.


class ModuloDeImpressao {
    constructor() {
        this._codigo = 10;
    }
    imprime(nomes) {
        nomes.forEach(function(nome) {
        console.log(`${this._codigo}: ${nome}`);
     }.bind(this));
   }
}

Como podemos ver, o bind vai passar um contexto para um função que não é dela, ou seja, o this._codigo dentro do forEach vai ter o contexto da classe ModuloDeImpressao.

Para saber mais

As Arrow functions tem outras propriedades interessantes como:

  • Retorno: Não precisamos declarar explicitamente o retorno quando temos um bloco apenas de código, a última expressão realizada vai ser o retorno da arrow function.

const soma = (numero1, numero2) => numero1 + numero2; 
soma(3,7) // 10
  • Nome: As Arrows functions ganham nome da variável atribuida quando da criação

const arrow = () => {};
arrow.name; // arrow
  • Construtor: Não é possível criar construtores com Arrow function

const Construtor = () => {};
new Construtor(); // Constructor is not a constructor

Se ficou interessado em como o Javascript funciona e como você pode utilizá-lo melhor, aqui na Alura temos uma formação em desenvolvimento Javascript. Nela, você verá como programar em Javascript, utilizar expressões regulares, dentre outras muitas coisas.

Felipe Nascimento
Felipe Nascimento

Desenvolvedor e instrutor na Alura com foco em JavaScript.

Veja outros artigos sobre Front-end