Como usar funções de seta no JavaScript

Como usar funções de seta no JavaScript

A sintaxe das funções de seta foi introduzida com o ECMAScript6: usando essa nova sintaxe, em alguns (mas não todos), podemos produzir um código mais conciso e legível, especialmente quando nossa função contém apenas uma expressão. Neste tutorial, veremos como podemos definir uma função de seta, quais são as diferenças com as funções padrão e quais são os casos em que o uso de funções de seta não é apropriado.

Neste tutorial, você aprenderá:

  • O que é uma função de seta.
  • Como uma função de seta é definida.
  • As diferenças entre as funções de seta e as funções padrão.
  • Os casos em que as funções de seta não podem ser usadas.

Requisitos de software e convenções de linha de comando Linux
Categoria Requisitos, convenções ou versão de software usada
Sistema Sistema Operacional Agnóstico.
Programas Uma instalação de Para seguir este tutorial em um ambiente não navegador.
Outro Conhecimento de conceitos JavaScript e Orientado a Objetos.
Convenções # - requer que os comandos Linux sejam executados com privilégios root diretamente como usuário root ou por uso de sudo comando
$ - Requer que os comandos do Linux sejam executados como um usuário não privilegiado regular

O que é uma "função de flecha"?

As funções de seta foram introduzidas com o ECMAScript6: Ao usar esta nova sintaxe, muitas vezes podemos obter um código mais conciso, em alguns casos traduzindo retornos de chamada de várias linhas para liners, graças a recursos como o retorno implícito. Por causa de suas peculiaridades, no entanto, as funções de seta não podem substituir as funções padrão em todos os lugares: existem alguns contextos em que não podemos usá -las, e vamos ver o porquê.



Das funções padrão às funções de seta

Neste parágrafo, veremos um exemplo de como podemos substituir uma função padrão por uma função de seta: usaremos um retorno de chamada de função de ordem superior como um exemplo perfeito de ao executar tal substituição.

Como você certamente sabe, um função de ordem superior é uma função que retorna outra função ou aceita outra função como um argumento. Neste exemplo, usaremos filtro, ou variedade.protótipo.filtro se você gostar. Este método do objeto de matriz, Tome uma função como seu argumento e retorna uma nova matriz, preenchida por todos os elementos da matriz original que são positivos para o teste implementado dentro da função de retorno de chamada.

Vamos ver um exemplo de usar filtro com uma função clássica. Imagine que temos uma variedade de objetos, Cada um deles representando personagens do livro "Senhor dos Anéis":

const caracteres = [name: 'frodO', raça: 'hobbit', name: 'sam', raça: 'hobbit', name: 'Legolas', raça: 'elf', name: ' Aragorn ', Race:' Man ', Nome:' Boromir ', Race:' Man '] 
cópia de

O personagens Array contém 5 elementos; Cada um deles tem duas propriedades: nome e corrida. Agora, suponha que queremos criar uma nova matriz povoada apenas pelos personagens que pertencem à raça dos homens. Usando o filtro e a sintaxe da função padrão, escrevemos:

const Men = personagens.filtro (função filteren (element) elemento de retorno.raça == 'homem'; ); 
cópia de

Como dito antes, filtro, Tome uma função como um argumento: ao usar a sintaxe padrão, essa função pode ser nomeada ou anônima. Na maioria das situações, as funções anônimas são usadas como retornos de chamada, mas por causa deste exemplo, e para destacar posteriormente uma das diferenças entre a sintaxe de funções padrão e de seta, demos um nome à nossa função: filteren.

A função de retorno de chamada a ser usada filtro, leva apenas um obrigatório parâmetro, que é o elemento da matriz original que está sendo processada a cada vez. Se a função retornar verdadeiro, O elemento é inserido como um membro da nova matriz, se a função retornar falso O elemento não é. Neste caso específico, definimos um teste simples:

personagem.raça == 'homem'
cópia de

Este teste retorna verdadeiro Se o corridapropriedade do elemento que está sendo processado, é igual à string 'homem'. Aqui está o resultado do que escrevemos acima:

[Nome: 'Aragorn', Race: "Man ', Nome:' Boromir ', Race:" Man'] 
cópia de

Agora, suponha que queremos refatorar o código acima usando um função de seta. Nós escrevíamos:

const Men = personagens.filtro (elemento => elemento.raça == 'homem'); 
cópia de

Usando o Funções de seta Sintaxe, conseguimos realizar o mesmo resultado do exemplo anterior com apenas uma linha de código: quão bom é isso?!. Não se preocupe se, à primeira vista.

A sintaxe da função de seta

Enquanto definimos uma função padrão usando o função palavra -chave, uma função de seta é definida usando o => símbolo. Obviamente, essa não é a única diferença entre os dois: um dos mais importantes que devemos destacar aqui é que, embora as funções clássicas, nas expressões de função, possam ser nomeadas ou anônimas, as funções de seta são sempre anônimas.



Definindo argumentos nas funções de seta

No exemplo anterior, já que nos livramos do função Palavra -chave, a primeira coisa que podemos ler é elemento, qual é o argumento aceito pela função de seta. A regra a seguir ao definir os argumentos esperados por uma função de seta é simples: se a função aceitar vários argumentos ou nenhum argumento, devemos incluí -los entre parênteses; Se a função contiver apenas um argumento, como é o caso em nosso exemplo, podemos omitir completamente os parênteses.

Como exemplo, imagine que queremos definir uma função que retorne o produto de dois números passados ​​como seus argumentos. Nós escrevíamos:

// Como a função leva dois parâmetros, devemos usar parênteses const const = (a, b) => a * b; 
cópia de

Retorno implícito e aparelho encaracolado

Em todos os exemplos acima, você pode ter notado a ausência de outra coisa: o aparelho encaracolado que delimita o corpo da função. Por que os omitimos? Se o corpo da função de seta consistir em apenas uma expressão, os aparelhos encaracolados poderão ser omitidos: se for o caso, o resultado da expressão será devolvido implicitamente:

// Se omitirmos aparelhos encaracolados, o resultado da expressão é implicitamente retornado const multiply = (a, b) => a * b; multiplicar (2,3); 6 // O resultado é 6: é implicitamente retornado // Se usarmos aparelhos encaracolados, o resultado não será implicitamente retornado const multiply = (a, b) => a * b multiply (2,3); O resultado indefinido será indefinido, pois não retornamos explicitamente o resultado da expressão 
cópia de

No código acima, definimos uma função muito simples, multiplicar: Esta função espera dois parâmetros, portanto devemos incluí -los entre parênteses. O => Símbolo define a função de seta. No primeiro exemplo, como temos apenas uma expressão, que retorna o produto dos dois números passados ​​como parâmetros, podemos omitir aparelhos encaracolados e tirar proveito do recurso de retorno implícito.

No segundo exemplo, usamos os aparelhos encaracolados, portanto a função retornou indefinido, Como não temos retorno implícito: obter o resultado esperado, deveríamos ter usado retornar explicitamente.

Múltiplas declarações ou expressões no corpo da função

Aparelhos encaracolados também são a única maneira de especificar várias declarações ou expressões dentro de uma função de seta. Por exemplo, suponha que, em vez de devolver o produto de dois números, queremos que nossa função produz uma string, exibindo -a:

const multiply = (a, b) => const produto = a*b; console.log ('O produto de $ a e $ b é $ Product');  multiplicar (2,3); O produto de 2 e 3 é 6 
cópia de

E se nossas funções de flecha tiverem que devolver um objeto literal, ele próprio delimitado por aparelhos encaracolados? Nesse caso, devemos incluir o objeto literal entre parênteses:



const CreateChar = (Caractername, CaracterRace) => (Nome: CharacterName, Race: CaracterRace); createChar ('gimli', 'anão') name: "gimli ', raça:" anão' 
cópia de

Como esse comporta funções dentro da flecha

Uma das mais relevantes, se não a diferença mais relevante entre as funções clássicas e as funções de seta é como o esse funciona. Essa diferença é a principal razão pela qual, em alguns casos, não podemos usar funções de seta, como veremos em breve. Antes de destacar as diferenças, Vamos recapitular como esse funciona quando é usado em funções padrão. A primeira coisa a lembrar é que, o valor de esse é determinado pela forma como a função em si é chamada, vamos ver alguns exemplos.

O padrão: esse é uma referência ao escopo global

Quando esse é usado dentro de uma função independente, e não estamos trabalhando em modo estrito, é referências o escopo global, que é o janela objeto em um ambiente de navegador, ou o objeto global no nó.JS. Na mesma situação, mas no modo rigoroso, esse vai ser indefinido E vamos receber um erro:

var i = 20; // Aqui usamos VAR em vez de Let, porque o último não cria uma propriedade no escopo global. function foo () console.log (isso.eu);  // Modo não rito foo () 20 // Modo rigoroso Foo () TypeError: Não é possível ler a propriedade 'i' de indefinido 
cópia de

Ligação implícita

Quando uma função padrão é referenciada dentro de um objeto, e essa função é chamada com esse objeto como um contexto, Usando a notação de ponto, esse torna -se uma referência a esse objeto. Este é o que chamamos ligação implícita:

function foo () console.log (isso.eu);  deixe objeto = i: 20, foo: foo // a propriedade foo é uma referência à função foo objeto.foo () // esta é uma referência ao objeto, então este.Eu sou objeto.I 20 
cópia de

Ligação explícita

Dizemos que estamos usando um ligação explícita Quando estamos declarando explicitamente o que esse deve referência. Pode ser realizado usando o chamar, aplicar ou vincular Métodos de uma função (que em JavaScript é um objeto de primeira classe. Lembre -se do primeiro caso que mencionamos acima, quando a ligação padrão se aplica:

var i = 20; function foo () console.log (isso.eu);  const object = i: 100 foo () // Isso produzirá 20 ou gerará um TypeError no modo rigoroso. // Se definirmos explicitamente isso como uma referência para objetar as coisas mudam. // Ligue e aplique execute a função imediatamente com o novo contexto: foo.Chamada (objeto) // a saída é 100 foo.aplicar (objeto) // a saída é 100 // em vez disso, retorna uma nova função com o contexto especificado. Deixe Boundfoo = Foo.bind (object) boundfoo () // a saída é 100 
cópia de

São algumas diferenças entre chamar, aplicar e vincular: o relevante é que o último retorna um nova função ligado ao contexto especificado, enquanto com os outros dois, a função, ligada ao contexto especificada, é executada imediatamente. Existem outras diferenças, mas não as veremos aqui. O importante é entender como explicitamente a ligação funciona.

Como as funções de seta são diferentes em esse respeito?

Em todos os casos e exemplos acima, vimos como, ao usar funções padrão, o valor de esse depende de como a função é chamada. Funções de seta, em vez disso, use o lexical isso: Eles não têm seus próprios esse, mas sempre use o esse De seu escopo fechado. Um exemplo típico em que isso pode produzir efeitos inesperados é nos ouvintes de eventos. Suponha que tenhamos um botão com ID "Button1" e queremos alterar seu texto quando ele é clicado:



Clique em mim! // O ouvinte do evento com uma função padrão como documento de retorno de chamada.getElementById ('Button1').addEventListener ('click', function () this.INNERTEXT = "Clicou!";) 
cópia de

O código funciona perfeitamente e, uma vez que o botão é clicado, seu texto muda conforme o esperado. E se usarmos uma função de seta neste caso? Suponha que escrevamos assim:

documento.getElementById ('Button1').addEventListener ('click', () => this.INNERTEXT = "Clicou!";) 
cópia de

O código acima não funciona, por que? Fácil: porque, como dissemos antes, enquanto no primeiro exemplo, esse Dentro da função de retorno de chamada padrão faz referência ao objeto no qual o evento ocorre (o botão), quando usamos a função de seta esse é herdado do escopo dos pais, que neste caso é o janela objeto. Por uma questão de completude, devemos dizer que o exemplo acima pode ser facilmente consertado para funcionar com uma função de seta:

documento.getElementById ('Button1').addEventListener ('click', evento => evento.alvo.INNERTEXT = "Clicou!";) 
cópia de

Desta vez, o código funciona porque não usamos esse Para fazer referência ao botão, mas deixamos nossa função aceitar um argumento, que é evento. No corpo da função que usamos evento.alvo Para referenciar o objeto que despachou o evento.

Pelo mesmo motivo que mencionamos acima, as funções de seta não podem ser usadas como métodos de objetos ou métodos de protótipo:

// As funções de seta não funcionam como métodos de objeto… const object1 = i: 1000, foo: () => console.log ('o valor de i é $ this.i ') objeto1.foo () o valor de i é indefinido //… e eles não funcionam como métodos de protótipo. const Pessoa = função (nome, idade) this.nome = nome; esse.idade = idade;  Pessoa.protótipo.introduce = () => console.log ('meu nome é $ this.nome e eu sou $ this.idade anos '); const Jack = nova pessoa ('Jack', 100); Jack.Nome 'Jack' Jack.100 anos Jack.Introduce () meu nome está indefinido e eu tenho anos indefinido 
cópia de

Conclusões

A sintaxe da função de seta é um recurso muito bom introduzido com o ecmascript6. Com esta nova maneira de definir funções, podemos escrever um código mais curto e limpo. Vimos como definir uma função de seta e como a nova sintaxe funciona.

Também vimos por que as funções de seta não podem substituir as funções padrão em todas as circunstâncias, porque elas não têm seus próprios esse, e usa o de seu escopo anexante: isso, como vimos neste tutorial, os torna não utilizáveis ​​como métodos ou construtores. Se você estiver interessado em outros tutoriais de JavaScript, fique atento: no próximo tutorial, falaremos sobre o buscar, função. Enquanto isso, você pode verificar nosso artigo sobre promessas.

Tutoriais do Linux relacionados:

  • Bash Regex avançado com exemplos
  • Introdução às Loops de JavaScript
  • Uma introdução à automação, ferramentas e técnicas do Linux
  • Mastering Bash Script Loops
  • Coisas para instalar no Ubuntu 20.04
  • Loops aninhados em scripts de basquete
  • Bash regexps para iniciantes com exemplos
  • Mint 20: Melhor que o Ubuntu e o Microsoft Windows?
  • Tutorial de depuração do GDB para iniciantes
  • Crie redirecionar e reescrever regras para .htaccess no apache…