Categorias
Artigos Home JavaScript

JavaScript funcional

Olá, neste artigo apresento alguns dos conceitos fundamentais para o JavaScript moderno: programação funcional. Bons estudos!

Prof. Diego Mariano

Variáveis em JavaScript

Em computação, uma variável é um nome associado a um espaço na memória utilizado para armazenar dados durante o desenvolvimento de software.

Para declarar uma variável podemos usar uma palavra-chave de declaração seguido do nome. Em JavaScript variáveis são case-sensitive, isto é, nomes escritos em letras maiúsculas são diferentes dos correspondentes em letras minúsculas. Nomes de variáveis devem iniciar preferencialmente com uma letra, ou com um dos símbolos: “_” ou “$”. Após a primeira letra, pode-se utilizar números ou ainda quaisquer caracteres Unicode (sim, podemos usar acentos e cedilha para nomear variáveis JavaScript, apesar de que recomendamos o uso de caracteres ASCII, o que inclui letras, números e “_” sublinhado).

Note que podemos declarar uma variável simplesmente escrevendo seu nome e atribuindo um valor a ela:

x = 10;

Essa forma cria uma variável global, o que não é recomendado (https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Grammar_and_Types). A melhor forma de armazenar dados na memória é usando uma das palavras-chave de declaração.

let, const, var

Há três formas de declaração no JavaScript: var, let e const.

  • var: declara uma variável global;

var x = 10;

  • let: declara uma variável de escopo;

let x = 10;

  • const: declara uma constante (ou seja, somente leitura).

const x = 10;

Observe a diferença entre var e let:

var

let

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Nesse exemplo, o valor de x é alterado duas vezes. Note que na declaração feita com let, o valor de x só é válido dentro do bloco (if), enquanto o valor de x declarado com var é global.

Note que se alterarmos o valor de x sem indicar a palavra de declaração, estamos alterando a variável global. Veja:

var

let

Interface gráfica do usuário, Aplicativo

Descrição gerada automaticamente

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Agora, veja o que acontece se declararmos uma const:

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Tipos de dados

Há sete tipos de dados em ECMAScript:

#

Tipo

Descrição

Exemplo

1

Boolean

Verdadeiro (true) ou falso (false)

let x = true;

2

null

Variável nula (deve ser escrito em minúsculo)

let x = null;

3

undefined

Variável indefinida

let x = undefined;

4

Number

Variável numérica. Pode ser inteira ou de ponto flutuante.

let x = 3.14;

5

String

Textos. Pode ser declarada com aspas ou apóstrofos.

let x = “Olá mundo!”;

6

Symbol

Usados internamente como chaves de propriedades de objetos. Não se pode fazer operações com o tipo Symbol.

let x = Symbol();

7

Object

Objetos são estruturas de dados usadas para criar o equivalente em outras linguagens a listas, arrays, dicionários, arrays associativos, dentre outros.

let x = {
“a”:”abacate”,

“b”:”bola”,

“c”:”casa”

}

Objetos são um tipo de dados especiais, portanto, se difere dos outros tipos primitivos. Podemos acessar cada elemento chamando o nome do objeto seguido da posição desejada dentro de colchetes.

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Observe como criamos um objeto do tipo array e acessamos cada posição. Arrays são variáveis que armazenam dados sequenciais e os indexa com base na posição da lista (a contagem começa com zero).

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Funções

Funções são blocos de códigos que realizam procedimentos podendo retornar valores e que são executados apenas quando chamados.

Declarando uma função

Podemos declarar uma função utilizando a palavra-chave function seguido de um nome e parênteses. Observe uma função simples que apenas exibe uma mensagem no console.

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Note que ao executar esse código, nada acontecerá, uma vez que códigos em uma função só são executados quando a função for chamada. Podemos chamar a função declarando seu nome seguido de parênteses:

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Note que a chamada da função deve ser feita após a declaração.

Passando parâmetros de parâmetros

Funções podem receber valores como entrada.

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Código-fonte

// declaração

function saudacao(nome){

console.log(“Olá, “+nome+”!”);

}

// chamada

saudacao(“José”);

Note que podemos chamar uma função, quantas vezes acharmos necessário:

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Return

Podemos ainda retornar valores no final de uma função utilizando a palavra-chave return.

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Função anônima

Uma função anônima é simplesmente uma função sem nome. A seguir declaramos uma função anônima que retorna a soma de três números:

(function (a, b, c){ return a + b + c; });

Note que o código acima não será executado. Para isso, precisamos executar a função imediatamente após a sua declaração ou podemos atribuir a expressão a uma variável. Veremos isso a seguir.

IIFE (Immediately Invoked Function Expression)

Podemos executar uma função anônima imediatamente após sua declaração aplicando os valores de entrada entre parênteses logo a seguir. Por exemplo:

Isso é denominado como Immediately Invoked Function Expression (IIFE), que poderia ser traduzido como expressão de função invocada imediatamente. Note que a função anônima aqui é chamada de function express.

Function expression

Uma expressão de função (function expression) se difere de uma declaração de função tradicional na forma a qual declaramos um nome.

Códigos com um mesmo objetivo construídos com base em funções declaradas tradicionalmente (function declaration) e expressões de funções (function expression)

function declaration

Uma imagem contendo Texto

Descrição gerada automaticamente

function expression

No exemplo a seguir, vamos utilizar uma function expression para construir uma função de soma:

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Note que podemos fazer uma cópia de uma function expression apenas atribuindo-a a outra variável. Observe:

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Existem formas mais reduzidas de escrever funções. Um exemplo disso são as chamadas arrow functions.

Arrow functions

Arrow functions, ou na tradução para o português “funções de seta”, são um tipo de sintaxe utilizada para escrever funções de forma mais condensada. Observe a sintaxe do uso de uma arrow function:

variável = (parâmetros) => { /* … */ };

Observe um exemplo a seguir:

Códigos com um mesmo objetivo construídos com base expressões de funções tradicionais e em funções de seta (arrow functions).

function expression

arrow function

Note que a sintaxe da arrow funcions é um mais simples do que uma function expression tradicional. Além disso, podemos simplificar ainda mais esse código. Por exemplo, quando temos um único parâmetro, não precisamos declarar parênteses:

Podemos chamar essa função, executando x(valor).

No exemplo acima, a função armazenada em “x” é similar ao código incrementa apresentado anteriormente. Mas podemos simplificar mais ainda. Se o código possuir apenas uma linha de código, não precisamos incluir as chaves { }. Além disso, se a função em questão apenas retornar um determinado valor, a palavra-chave se torna desnecessária. Assim, o código a seguir faz as mesmas coisas que os códigos anteriores:

Texto

Descrição gerada automaticamente com confiança média

Note como as funções x e y obtém resultados idênticos:

Interface gráfica do usuário, Texto, Aplicativo, Teams

Descrição gerada automaticamente

Agora, vamos usar o que aprendemos para criar uma função de soma simples:

Texto

Descrição gerada automaticamente

Função invocada

Agora vamos combinar as habilidades que aprendemos anteriormente. O código a seguir, declara uma função anônima que é invocada imediatamente:

Vamos entender parte por parte desse código:

Código

Descrição

(

o primeiro “(“ indica um escopo geral.

( )

// () indica que nenhuma variável está sendo passada para a função anônima 

=>

Indica que se trata de uma arrow function.

console.log(‘invocando uma função)

Comando principal.

)

Fechamento do “)” inicial.

( );

Executa a função imediatamente.

O uso arrow functions e invocação imediata de funções reduz a verbosidade da linguagem, mas pode levar a erros. Portanto, tenha cuidado para não se perder no meio de tantos parênteses.

Operador spread (…valores)

Podemos criar uma função que recebe três parâmetros e os imprime na tela da seguinte forma:

Note que JavaScript não irá gerar erros se chamarmos essa função passando parâmetros a mais:

Interface gráfica do usuário, Aplicativo

Descrição gerada automaticamente

Entretanto, se passarmos parâmetros a menos, eles receberão o valor undefined:

Texto

Descrição gerada automaticamente

Note que podemos atribuir um valor padrão, que será aplicado apenas se o valor não for atribuído na chamada da função.

Texto

Descrição gerada automaticamente

Caso atribua um valor a aquela posição, o valor padrão será substituído.

Interface gráfica do usuário, Aplicativo

Descrição gerada automaticamente

Agora, observe o exemplo a seguir:

Interface gráfica do usuário, Texto

Descrição gerada automaticamente

Esse código irá imprimir os valores de 1 a 6. Com base no que vimos acima, se eu adicionasse um sétimo número, ele não seria exibido pela função.

Podemos resolver esse problema usando o operador spread/rest antes do nome do array. O operador spread/rest é declarado com três pontos seguidos “…”:

Agora vamos reproduzi-lo usando o operador spread/rest

Texto

Descrição gerada automaticamente

Veja um exemplo prático. O código a seguir, recebe uma lista de números e imprime o quadrado dele:

Texto

Descrição gerada automaticamente com confiança baixa

Execício

Construa uma função que reproduza os efeitos da função range(). Ela deve receber até 3 parâmetros: (1) valor de início; (2) valor final; e (3) passo.

Faça os seguintes testes e verifique se os resultados são idênticos aos apresentados a seguir:

  1. range(5) -> [1, 2, 3, 4, 5]
  2. range (6, 11) -> [6, 7, 8, 9, 10, 11]
  3. range(10, 19, 2) -> [10,12,14,16,18]
  4. range(6, 2) -> [6, 5, 4, 3, 2]
  5. range(8, -3, 4) -> [8, 4, 0]

Resposta:

Texto

Descrição gerada automaticamente

const exercicio = ((inicio, fim = 0, passo = 1) => {

r = [];

if(fim==0){

for(let i of Array(inicio).keys()){            

r.push(i+passo)

}

}

else if(fim > inicio){

for(let i=inicio; i <= fim; i+=passo){

r.push(i)

}

}

else if(fim < inicio){

for(let i=inicio; i >= fim; i-=passo){

r.push(i)

}

}

return r;

});

Agora, vejamos os testes:

Texto, Carta

Descrição gerada automaticamente

First-class function

First-class function, ou na tradução “função de primeira classe”, é uma característica de linguagens de programação que permitem que funções possam ser tratadas como uma variável (https://developer.mozilla.org/pt-BR/docs/Glossary/First-class_Function).

Já vimos isso anteriormente quando falamos de function expression. Entretanto, ainda não demos a devida atenção a um importante uso dessa característica: a possibilidade de passar uma função como parâmetro de outra função.

Agora, observe o que acontece quando executamos a função saudacao():

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Neste caso, a função saudacao() faz uma chamada à função mensagem(). Note que neste caso estamos lidando com strings, entretanto, podemos ir mais além e retornar outras funções. Chamamos isso de funções de mais alta ordem.

Saiba mais

Podemos usar os conhecimentos que adquirimos nos blocos anteriores para criar funções que realizam a soma, subtração, divisão e multiplicação de diferentes formas. Observe:

const add = (a, b) => { return a+b }

const subt = (a, b) => a-b

const mult = function(a, b){ return a * b }

const divi = (a, b) => a/b

Agora observe como podemos usar essas funções atribuídas a variáveis:


Higher-order function

Um outro conceito diretamente relacionado às funções de primeira classe são as funções de mais alta ordem (higher-order function). Higher-order functions são como são denominadas as funções que retornam uma outra função.

No exemplo apresentado a seguir, a função saudacao() será alterada para retornar uma outra função:

Interface gráfica do usuário, Texto, Aplicativo, Email

Descrição gerada automaticamente

Aqui, vemos que nossa função retorna um objeto de uma função. Para que ele apenas imprima a mensagem, podemos usar dois parênteses:

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Objetos em JavaScript

Em JavaScript, retirando os tipos de dados primitivos, como null e undefined, tudo é um objeto[1]. Mesmo dados primitivos como strings e números podem ser manipulados como se fosse objetos: JavaScript cria um wrapper que os transforma em objetos[2].

Objetos possuem propriedades e métodos. Informalmente, propriedades podem ser definidas de forma similar a variáveis que recebem valores, enquanto métodos são funções que desempenham ações específicas para aquele tipo de objeto. Observe como podemos acessar um objeto:

  • objeto.propriedade
  • objeto.método( )

onde objeto é o nome da variável escolhida para armazenar os dados desse objeto em questão, a propriedade é um nome específico que armazena um valor (que pode ser string, número ou até mesmo outros objetos) e método( ) corresponde a uma função que aplica alterações no objeto em questão.

Objetos literais do JavaScript podem ser declarados por meio de uma coleção de chaves e valores separados por dois-pontos e são declarados usando chaves { }. Para acessar determinada chave, apenas indicamos o nome da variável que recebe o objeto, seguida de colchetes e da chave usada. Veja um exemplo:

Interface gráfica do usuário

Descrição gerada automaticamente

Podemos também acessar um objeto usando o símbolo “.” seguido da chave que se deseja acessar:

Gráfico

Descrição gerada automaticamente com confiança baixa

Para criar uma nova propriedade, basta apenas atribuir um novo valor ao nome escolhido:

Uma imagem contendo Interface gráfica do usuário

Descrição gerada automaticamente

Arrays em JavaScript

Em JavaScript, arrays (ou listas) são considerados um tipo de objeto. Podemos criar objetos do tipo array usando valores separados por vírgulas dentro de colchetes [ ]. Cada elemento de um array pode ser acessado por sua posição de inserção (note que a contagem começa em zero). Por exemplo:

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Note que não podemos acessar determinado valor de um objeto usando o operador “.”:

Interface gráfica do usuário, Texto, Aplicativo, chat ou mensagem de texto

Descrição gerada automaticamente

Essa notação é válida apenas para objetos que possuem propriedades vinculadas aos valores. Arrays utilizam um índice numérico para indicar a posição de cada item.

Podemos ainda iterar por um array usando o método forEach(), que recebe como parâmetro uma função com dois argumentos: (1) item correspondente e (2) posição no índice. Veja um exemplo:

Tabela

Descrição gerada automaticamente com confiança baixa

Note que forEach é um método de um objeto. Portanto, sua chamada é feita separada por ponto, seguido do nome do método e de parênteses.

Para adicionar dados a um array use o método push( ), que irá retornar a posição da inserção:

Uma imagem contendo Gráfico

Descrição gerada automaticamente

Remova o último item com pop( ):

Gráfico

Descrição gerada automaticamente com confiança baixa

Você pode realizar buscas por determinados valores usando o método indexOf( ):

Interface gráfica do usuário

Descrição gerada automaticamente com confiança média

Funções de arrays

Podemos manipular arrays de forma mais funcional usando as funções map, reduce e filter.

map() – para cada item do array, aplique uma função

  • A função map( ) mapeia cada item de um array a uma determinada função.
  • Retona um array de mesmo tamanho com valores transformados pela função.
  • Sintaxe: objeto.map(função, índice)

Por exemplo, vamos criar uma função que normalize notas de estudantes:

Texto

Descrição gerada automaticamente

Agora vamos pegar todas as notas:

Podemos verificar qual a maior nota rodando:

Interface gráfica do usuário, Texto

Descrição gerada automaticamente

Agora normalizamos as notas usando:

Interface gráfica do usuário, Texto

Descrição gerada automaticamente com confiança média

Neste exemplo, usamos map( ) para aplicar uma função que normaliza os dados. Veja que para esse exemplo, optamos por não utilizar o índice (apenas um argumento foi passado para a função map).

Podemos ver todas as notas executando:

Uma forma mais simples de se fazer isso seria separando a função que normaliza aplicando-a a uma variável, seguido do mapeamento delas.

Interface gráfica do usuário, Texto, Aplicativo, chat ou mensagem de texto

Descrição gerada automaticamente

Note que usamos map( ) duas vezes: na primeira coletamos apenas as notas do objeto estudantes e em seguida aplicamos a função normaliza para cada nota obtida.

Perceba que podemos até mesmo aplicar map( ) em outras funções que definimos anteriormente como por exemplo, o código que calcula a maior nota, que era feito assim:

Pode ser refatorado usando uma única linha:

reduce() – reduz valores de um array para um único valor

  • A função reduce( ) reduz os itens de um array com base em uma função.
  • Retona um único valor.
  • Sintaxe: objeto.reduce(função)

Digamos que desejemos calcular a nota média da turma.

Texto

Descrição gerada automaticamente

Bom, agora nosso código ficou um pouco mais complicado. Vamos analisá-lo parte a parte:

Perceba que criamos uma function expression para receber o somatório de valores. Essa função recebe dois parâmetros e retorna a soma deles. Usaremos essa função na entrada da função reduce.

A seguir criamos uma variável chamada média. A média é a soma dos valores dividido pela quantidade de valores. Então, precisamos primeiro pegar os valores correspondentes. Fazemos isso quando usamos o comando:

estudantes.map(i=>nota)

A seguir, aplicamos a função reduce que recebe como entrada a função somatorio( ):

.reduce(somatorio)

Note que reduce pegará cada valor do array, aplicará um processamento e fará uma chamada recursiva até que todos os valores tenham sido analisados. No caso, fará o somatório de todos os valores presentes no array. Por fim, precisamos dividir pela quantidade de alunos presentes na lista. Podemos fazer isso usando:

/ estudantes.length

Desta forma, conseguimos usar reduce( ) para calcular a média.

filter() –filtra os dados de um array

  • A função filter( ) filtra os itens de um array com base em uma função.
  • Retona um array de tamanho <= ao tamanho do array original.
  • Sintaxe: objeto.filter(função)

Digamos que desejemos obter apenas a lista de alunos que obtiveram nota superior a 6. Podemos fazer isso usando a função filter().

Vamos começar criando uma função que verifica se o aluno tirou nota maior que 6. Se sim, retorne todo o item:

Agora vamos aplicar o método filter( ) à lista de alunos passando como argumento a função aprovado. Observe que apenas dois alunos foram aprovados.

Uma imagem contendo Interface gráfica do usuário

Descrição gerada automaticamente

Mas lembre-se que havíamos definido anteriormente que as notas seriam normalizadas. Logo, a maior nota da sala, que foi 7.5, passaria a valer 10. Normalizamos anteriormente, mas não salvamos os dados no objeto estudantes. Vamos calcular as notas normalizadas e salvar em uma variável chamada novas_notas.

Vamos então salvar usando a função map( ) e o índice de cada valor.

Interface gráfica do usuário, Texto, Aplicativo

Descrição gerada automaticamente

Agora podemos ver quem foram os aprovados usando a função filter:

Diagrama

Descrição gerada automaticamente com confiança baixa

Os quatro estudantes foram aprovados – e o dia foi salvo graças à função filter( ) haha!

  1. https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Guide/Working_with_Objects#objetos_tudo

  2. https://blog.logrocket.com/javascript-typeof-2511d53a1a62

Quer aprender mais sobre Desenvolvimento Web?

Dá uma olhada nesses cursos disponíveis a partir de R$ 27,90 (e ainda dar uma moral para ajudar esse pobre professor a pagar seus boletos) 😉

Por Diego Mariano

Doutor em Bioinformática pela Universidade Federal de Minas Gerais com atuação na área de ciência de dados e aprendizado de máquina aplicados ao aperfeiçoamento de enzimas usadas na produção de biocombustíveis. Mestre em Bioinformática, também pela UFMG, atuando na área de desenvolvimento de sistemas Web para montagem de genomas. Atualmente realiza estágio pós-doutoral no Departamento de Ciência da Computação da UFMG com foco em desenvolvimento de sistemas Web para Bioinformática, análise exploratória e visualização de dados. Tem conhecimentos nas linguagens: PHP, JavaScript, Python, R, Perl, HTML, CSS e SQL.

2 respostas em “JavaScript funcional”

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.

error

Compartilhe este post!

Facebook
YouTube
LinkedIn
Instagram