Nome: ? | Matrícula: ?

JavaScript: funções de alta ordem e escopo

JavaScript (JS) é uma linguagem de programação dinâmica, de tipificação fraca e interpretada. Ela foi criada em 1995 pela Netscape Communications, empresa que desenvolveu um dos primeiros navegadores web. Mais tarde, a linguagem foi formalizada na especificação ECMAScript (ES), que vem evoluindo desde então. No momento em que este texto foi escrito, a versão mais recente da especificação é a ECMAScript 2016 (anteriormente conhecida como ECMAScript 7), mas mesmo o ECMAScript 2015, ou ECMAScript 6 não é suportado completamente por todos os navegadores. Projetos como o Babel permitem transformar código de uma versão mais recente para uma versão mais antiga da especificação.

Estruturas básicas

Strings

Strings podem ser escritas com ", ' ou `. Em qualquer caso, você pode usar a barra invertida (\) para “escapar” um caractere que do contrário teria um significado especial. Exemplo:

function(str, info) { return simplesEval(str, info); }

Apenas as strings com acento grave (`) permitem interpolação de strings:

function(str, info) { return simplesEval(str, info); }

Se o let e o ` não funcionarem, seu navegador pode estar desatualizado. Você pode conseguir rodar trocando por var e " (embora o resultado não seja exatamente igual).

Objetos

Objetos em JavaScript são estruturas chave-valor, similar a estruturas que em outras linguagens são chamadas de hash, mapa ou dicionário. As chaves são chamadas propriedades do objeto. Exemplo:

function(str, info) { return simplesEval(str, info); }

Para saber mais: Working with objects (Mozilla Developer Network).

Arrays

Um array em Javascript (ex.: [1, 2, 3]) é um objeto mutável, isto é, ele pode ser modificado. As funções que modificam o array são chamadas de funções destrutivas. As funções não-destrutivas são aquelas que não modificam o array; em vez disso, elas retornam um novo array que é construído a partir de um array pré-existente.

Do ponto de vista das linguagens funcionais, uma função deve apenas receber valores como parâmetro e retornar um valor. Se a função modifica algum parâmetro, altera variáveis globais, ou acessa entrada/saída (ex.: modifica um arquivo), esses comportamentos são considerados efeitos colaterais de se chamar a função, e a função é dita não-pura.

Uma função pura, sem efeitos colaterais, vai sempre retornar o mesmo resultado para uma determinada entrada, não importa quantas vezes a função seja chamada.

A seguir, algumas operações sobre arrays. Nos exemplos, considere que a é um array.

Operação destrutiva não-destrutiva
Obter primeiro elemento   x = a[0]
Obter restante da lista a.shift() l = a.slice(1)
Adicionar x ao final a.push(x) l = a.concat([x])
Comprimento do array   x = a.length
Criar uma cópia da lista   l = a.slice()

Funções como cidadãos de primeira classe

Como já vimos, JavaScript é uma linguagem na qual funções são cidadãos de primeira classe, isto é, elas podem ser atribuídas a variáveis, passadas como parâmetro e retornadas de outras funções.

Exemplo:

function cumprimenta() {
    alert('Oi, tudo bom?');
}

let botao = document.getElementById('botao1');
botao.addEventListener('click', cumprimenta);

Nesse exemplo, a função cumprimenta foi passada como parâmetro para a função addEventListener (tecnicamente, addEventListener é um método – já que JavaScript é orientada a objetos – mas na prática é muito semelhante a uma função).

Funções de alta ordem

Exemplo de função que recebe função como parâmetro, executando a função 3 vezes, cada vez passando um número:

function(str, info) { return simplesEval(str, info); }

Note que, desta vez, definimos uma função anônima, function (x) { console.log('Dou-lhe ' + x); }.

JavaScript já define algumas funções de alta ordem importantes, como a função map:

function(str, info) { return simplesEval(str, info); }

Ou a função forEach, para iterar sobre os elementos:

function(str, info) { return simplesEval(str, info); }

Funções de alta ordem em JavaScript para arrays: forEach, filter, map, reduce, some, every, find, findIndex.

Funções anônimas (sintaxe nova)

Há uma notação compacta para definir funções anônimas: x => x * 2 (função que recebe um argumento, x e retorna o seu dobro). Outros exemplos:

(Experimente converter essa notação para JavaScript antigo)

Exemplo:

function(str, info) { return simplesEval(str, info); }

Exercícios

map

Implemente a função meuMap em JavaScript:

(Duas implementações possíveis: criando um array e modificando-o com operações destrutivas, ou usando apenas operações não-destrutivas; )

function(str, info) { return simplesEval(str, info); }

Filmes

(Baseado em http://reactivex.io/learnrx/.)

Nos exemplos a seguir, considere os seguintes dados (execute o código para carregar a variável filmes na memória):

function(str, info) { return simplesEval(str, info); }

map

Use a função map para mapear o array em um novo array contendo somente os títulos dos filmes

function(str, info) { return simplesEval(str, info); }

filter

Use a função filter para selecionar apenas os filmes com notas superior a 4.

function(str, info) { return simplesEval(str, info); }

map e filter

Agora combine map e filter para retornar apenas os títulos dos filmes com nota superior a 4.

function(str, info) { return simplesEval(str, info); }

reduce

A função reduce aplica uma função dada a um acumulador e cada elemento do array para reduzir o array a um único valor. A sintaxe é:

arr.reduce(f, valorInicial), onde

Por exemplo, considere a função somatório, que retorna o somatório dos elementos de um array, escrito da forma tradicional, com for:

function(str, info) { return simplesEval(str, info); }

A função pode ser escrita de forma mais compacta usando o reduce:

function(str, info) { return simplesEval(str, info); }

Exemplo para somar as notas dos filmes:

function(str, info) { return simplesEval(str, info); }

reduce (máximo)

Agora use reduce para retornar a maior nota do conjunto.

Dica: use o operador ternário ?:. A expressão condicao ? x : y retorna x se a condicao for verdadeira, e y caso contrário.

function(str, info) { return simplesEval(str, info); }

(Você também pode tentar calcular a maior nota sem usar funções de alta ordem. O código será muito mais longo.)