Introdução
Em JavaScript, funções são cidadãs de primeira classe: elas podem ser atribuídas a variáveis, passadas como argumentos para outras funções e retornadas como resultado de outras funções. Esse comportamento é a base de padrões muito usados no desenvolvimento web — eventos de clique, requisições HTTP, temporizadores e muito mais.
Nesta unidade vamos estudar três formas de declarar funções, entender o conceito de escopo, aprender o que são callbacks e conhecer as funções de ordem superior mais usadas no dia a dia com JavaScript.
.js e executados com
node arquivo.js no terminal, ou colados diretamente no console do
navegador (F12 → aba Console). Recomendamos reproduzir e modificar cada exemplo
antes de avançar para o próximo.
1. Funções em JavaScript
1.1 Declaração de função
É a forma mais clássica. A palavra-chave function é seguida pelo
nome, pelos parâmetros entre parênteses e pelo corpo entre chaves.
// Declaração de função
function saudar(nome) {
return "Olá, " + nome + "!";
}
// Chamando (invocando) a função
console.log(saudar("Ana")); // Olá, Ana!
console.log(saudar("João")); // Olá, João!
function saudar(nome)— declara uma função chamadasaudarque recebe um parâmetro chamadonome.return— devolve um valor para quem chamou a função. Semreturn, a função retornaundefined.saudar("Ana")— chama a função passando"Ana"como argumento. O parâmetronomerecebe esse valor dentro da função.
1.2 Expressão de função
Uma função também pode ser atribuída a uma variável. Essa forma é chamada de expressão de função. A diferença prática é que expressões de função não são içadas (hoisting) — precisam ser definidas antes de serem usadas.
// Expressão de função
const dobrar = function(numero) {
return numero * 2;
};
console.log(dobrar(5)); // 10
console.log(dobrar(12)); // 24
console.log(typeof dobrar); // "function"
1.3 Parâmetros com valor padrão
JavaScript permite definir valores padrão para parâmetros, usados quando o argumento não for passado pelo chamador.
function criarMensagem(texto, autor = "Anônimo") {
return `"${texto}" — ${autor}`;
}
console.log(criarMensagem("Aprender é crescer", "Maria"));
// "Aprender é crescer" — Maria
console.log(criarMensagem("Tente sempre"));
// "Tente sempre" — Anônimo ← usou o valor padrão
`) com ${} é chamado de
template literal. Ele permite embutir expressões JavaScript
diretamente dentro de strings, sem precisar concatenar com +.
1.4 Funções que retornam funções
Como funções são valores, uma função pode retornar outra função. Esse padrão será muito útil quando estudarmos closures e callbacks.
function criarMultiplicador(fator) {
// Retorna uma nova função que usa "fator" do escopo externo
return function(numero) {
return numero * fator;
};
}
const triplicar = criarMultiplicador(3);
const quadruplicar = criarMultiplicador(4);
console.log(triplicar(5)); // 15
console.log(quadruplicar(5)); // 20
- c
riarMultiplicador(3)executa e retorna uma função que multiplica por 3. Essa função é guardada emtriplicar. - Quando chamamos
triplicar(5), a função interna ainda "lembra" quefatoré 3 — mesmo depois decriarMultiplicadorter terminado. Isso é chamado de closure.
Outro exemplo simples para entender melhor:
function criarContador() {
let contador = 0; // variável do escopo externo
return function () { // função interna — a closure
contador++;
console.log(contador);
};
}
const contarA = criarContador(); // estado A
const contarB = criarContador(); // estado B — separado!
contarA(); // 1
contarA(); // 2
contarB(); // 1 ← começa do zero
contarA(); // 3
2. Escopo em JavaScript
Escopo define onde uma variável pode ser acessada no código. Em JavaScript moderno existem três escopos principais:
2.1 Escopo global
Variáveis declaradas fora de qualquer função ou bloco são globais — acessíveis em qualquer lugar do código.
const disciplina = "Programação II"; // variável global
function exibir() {
// Pode acessar variável global aqui dentro
console.log(disciplina);
}
exibir(); // Programação II
console.log(disciplina); // Programação II
2.2 Escopo de função
Variáveis declaradas com var dentro de uma função existem apenas
dentro dela.
function calcular() {
var resultado = 42; // existe só dentro de calcular()
console.log(resultado); // 42
}
calcular();
// console.log(resultado); // ← ERRO: resultado is not defined
2.3 Escopo de bloco (let e const)
Com let e const (introduzidos no ES6ES6 é a 6ª versão da especificação ECMAScript — o padrão oficial que define como o JavaScript deve funcionar. Foi lançada em 2015 e é também chamada de ES2015.), variáveis ficam
restritas ao bloco { } em que foram declaradas — seja um
if, um for ou qualquer outro bloco.
if (true) {
let mensagem = "Dentro do bloco";
const constante = 100;
console.log(mensagem); // Dentro do bloco
console.log(constante); // 100
}
// console.log(mensagem); // ← ERRO: não existe aqui fora
// console.log(constante); // ← ERRO: não existe aqui fora
// Comparação com var (NÃO recomendado em código moderno):
if (true) {
var vazado = "var vaza do bloco";
}
console.log(vazado); // "var vaza do bloco" ← comportamento problemático
const por padrão.
Use let quando precisar reatribuir a variável. Evite
var em código moderno.
3. Arrow Functions
Introduzidas no ES6, as arrow functions são uma sintaxe mais curta para escrever funções. São muito usadas em callbacksCallback é uma função passada como argumento para outra função, para ser executada em algum momento — geralmente quando uma operação termina ou um evento ocorre. e em código JavaScript moderno.
3.1 Sintaxe básica
// Função tradicional
function somar(a, b) {
return a + b;
}
// Equivalente como arrow function
const somarArrow = (a, b) => {
return a + b;
};
// Versão ainda mais curta: retorno implícito (sem chaves e sem return)
const somarCurta = (a, b) => a + b;
console.log(somar(3, 4)); // 7
console.log(somarArrow(3, 4)); // 7
console.log(somarCurta(3, 4)); // 7
- Se houver um único parâmetro, os parênteses são opcionais:
x => x * 2 - Se não houver parâmetros, os parênteses são obrigatórios:
() => "olá" - Se o corpo tiver uma única expressão, as chaves e o
returnpodem ser omitidos — o resultado da expressão é retornado automaticamente. - Se o corpo tiver múltiplas linhas, use chaves e
returnexplícito normalmente.
3.2 Exemplos variados de sintaxe
// Um parâmetro: parênteses opcionais
const dobrar = x => x * 2;
// Sem parâmetros: parênteses obrigatórios
const dizerOla = () => "Olá!";
// Múltiplas linhas: chaves e return obrigatórios
const calcularDesconto = (preco, percentual) => {
const desconto = preco * (percentual / 100);
return preco - desconto;
};
console.log(dobrar(6)); // 12
console.log(dizerOla()); // Olá!
console.log(calcularDesconto(100, 10)); // 90
3.3 Diferença importante: o this
Arrow functions não possuem seu próprio this —
elas herdam o this do contexto em que foram criadas. Isso resolve
um problema clássico com funções tradicionais dentro de classes e eventos.
// Em funções tradicionais, "this" dentro do callback
// pode ser diferente do esperado:
function Contador() {
this.valor = 0;
// Arrow function: "this" vem do Contador, funciona corretamente
setInterval(() => {
this.valor++;
console.log(this.valor);
}, 1000);
}
const c = new Contador(); // imprime 1, 2, 3... a cada segundo
this ficará mais claro quando
trabalharmos com classes e eventos do DOM.
4. Callbacks
Um callback é uma função passada como argumento para outra função, para ser executada em algum momento posterior — quando um evento ocorre, quando uma operação termina, etc.
4.1 Callback simples
No exemplo abaixo, a função executar recebe outra função como
argumento e a chama internamente.
// "operacao" é um callback: uma função passada como argumento
function executar(operacao) {
console.log("Antes da operação");
operacao(); // chama o callback
console.log("Depois da operação");
}
// Passando uma função declarada
function minhaOperacao() {
console.log("Executando a operação!");
}
executar(minhaOperacao);
// Antes da operação
// Executando a operação!
// Depois da operação
minhaOperacao sem os parênteses.
minhaOperacao→ passa a função em si como valor.minhaOperacao()→ executa a função imediatamente e passa o resultado.
4.2 Callback com argumentos
Callbacks podem receber argumentos. O chamador decide o que passar quando invocar o callback.
function processarNota(nota, callback) {
if (nota < 0 || nota > 10) {
throw new Error("Nota inválida");
}
callback(nota);
}
function exibirResultado(nota) {
const situacao = nota >= 6 ? "Aprovado" : "Reprovado";
console.log(`Nota: ${nota} → ${situacao}`);
}
processarNota(8.5, exibirResultado); // Nota: 8.5 → Aprovado
processarNota(4.0, exibirResultado); // Nota: 4.0 → Reprovado
4.3 Callback com função anônima
Muitas vezes o callback é escrito diretamente no lugar da chamada, sem precisar de um nome. Esse é o padrão mais comum no código web real.
function processarNota(nota, callback) {
if (nota < 0 || nota > 10) throw new Error("Nota inválida");
callback(nota);
}
// Passando uma arrow function anônima diretamente como callback
processarNota(7, (nota) => {
console.log(`Nota recebida: ${nota}`);
});
// Nota recebida: 7
// Versão ainda mais curta com retorno implícito:
processarNota(5, nota => console.log(`Nota: ${nota}`));
// Nota: 5
4.4 Callback assíncrono — o caso mais comum na web
O uso mais frequente de callbacks na web é em operações que levam tempo: esperar um clique, um timer, uma resposta de rede. O código não trava — o callback só é chamado quando o evento acontece.
// setTimeout: executa o callback após um tempo (em milissegundos)
console.log("Início");
setTimeout(() => {
console.log("Isso aparece depois de 2 segundos");
}, 2000);
console.log("Fim"); // aparece ANTES do setTimeout
// Saída:
// Início
// Fim
// Isso aparece depois de 2 segundos
setTimeout.
Isso mostra o comportamento assíncrono: o JavaScript não
espera o timer terminar — ele continua executando o resto do código e,
quando o timer dispara, chama o callback. Esse modelo é a base de todo
o comportamento assíncrono em JavaScript.
5. Funções de ordem superior
Uma função de ordem superior (Higher-Order Function) é aquela que recebe uma função como argumento e/ou retorna uma função. Você já viu isso nos callbacks — agora vamos ver as funções de ordem superior mais usadas em JavaScript para trabalhar com arrays.
5.1 forEach — percorrer
Executa um callback para cada elemento do array. Não retorna nada.
const estudantes = ["Ana", "João", "Maria", "Pedro"];
estudantes.forEach((estudante, indice) => {
console.log(`${indice + 1}. ${estudante}`);
});
// 1. Ana
// 2. João
// 3. Maria
// 4. Pedro
5.2 map — transformar
Retorna um novo array com o resultado do callback aplicado a cada elemento. O array original não é alterado.
const notas = [6.0, 8.5, 4.0, 9.2];
// Adiciona 1 ponto em todas as notas
const notasAjustadas = notas.map(nota => nota + 1);
console.log(notas); // [6, 8.5, 4, 9.2] ← original intacto
console.log(notasAjustadas); // [7, 9.5, 5, 10.2]
// Transformando em objetos com situação
const resultado = notas.map(nota => ({
nota,
situacao: nota >= 6 ? "Aprovado" : "Reprovado"
}));
console.log(resultado);
// [ { nota: 6, situacao: 'Aprovado' },
// { nota: 8.5, situacao: 'Aprovado' },
// { nota: 4, situacao: 'Reprovado' },
// { nota: 9.2, situacao: 'Aprovado' } ]
map em vez de forEach?
- Use
forEachquando quiser apenas percorrer o array para fazer algo (ex: imprimir, salvar). - Use
mapquando quiser transformar o array em outro array de mesma quantidade de elementos.
5.3 filter — filtrar
Retorna um novo array contendo apenas os elementos para os quais o callback
retornou true.
const notas = [6.0, 8.5, 4.0, 9.2, 3.5, 7.0];
const aprovados = notas.filter(nota => nota >= 6);
const reprovados = notas.filter(nota => nota < 6);
console.log(aprovados); // [6, 8.5, 9.2, 7]
console.log(reprovados); // [4, 3.5]
5.4 reduce — acumular
Reduz o array a um único valor, acumulando o resultado do callback a cada iteração. É o mais poderoso e o mais complexo dos três.
const notas = [6.0, 8.5, 4.0, 9.2];
// Soma todas as notas
const soma = notas.reduce((acumulador, nota) => acumulador + nota, 0);
console.log(soma); // 27.7
// Calculando a média
const media = soma / notas.length;
console.log(media.toFixed(2)); // 6.93
reduce funciona passo a passo:
- O segundo argumento (
0) é o valor inicial do acumulador. - A cada iteração, o callback recebe o acumulador e o elemento atual, e retorna o novo acumulador.
- Iteração 1:
0 + 6.0 = 6.0 - Iteração 2:
6.0 + 8.5 = 14.5 - Iteração 3:
14.5 + 4.0 = 18.5 - Iteração 4:
18.5 + 9.2 = 27.7→ resultado final
5.5 Encadeamento de métodos
Como map e filter retornam novos arrays, podemos
encadear várias operações em sequência.
const estudantes = [
{ nome: "Ana", nota: 8.5 },
{ nome: "João", nota: 4.0 },
{ nome: "Maria", nota: 9.2 },
{ nome: "Pedro", nota: 5.5 },
];
// Nomes dos estudantes aprovados, em ordem alfabética
const nomesAprovados = estudantes
.filter(estudante => estudante.nota >= 6) // filtra aprovados
.map(estudante => estudante.nome) // extrai só o nome
.sort(); // ordena alfabeticamente
console.log(nomesAprovados); // ["Ana", "Maria"]
6. Para memorizar!
Exercício 1 – Funções e parâmetros padrão
Crie uma função apresentar que receba nome,
curso e de>semestre (padrão: 1) e retorne uma string
formatada com template literal. Exemplos de saída esperada:
apresentar("Ana", "Eng. Computação", 3)→ "Ana – Eng. Computação – 3º semestre"apresentar("João", "Eng. Computação")→ "João – Eng. Computação – 1º semestre"
Desafio: reescreva a função como arrow function.
Exercício 2 – Callbacks e validação
Crie uma função processarIdade que receba um número e um
callback. A função deve:
- Lançar um erro se a idade for negativa ou maior que 120.
- Chamar o callback com a idade se for válida.
Teste passando callbacks diferentes: um que exibe se a pessoa é maior de idade, outro que calcula o ano de nascimento aproximado.
Exercício 3 – map, filter e reduce
Dado o array de produtos abaixo, resolva cada item usando o método indicado:
const produtos = [
{ nome: "Mouse", preco: 80, estoque: 5 },
{ nome: "Teclado", preco: 150, estoque: 0 },
{ nome: "Monitor", preco: 900, estoque: 2 },
{ nome: "Headset", preco: 200, estoque: 8 },
{ nome: "Webcam", preco: 120, estoque: 0 },
];
- filter: retorne apenas os produtos com estoque maior que zero.
- map: aplique 10% de desconto em todos os preços e retorne um novo array com nome e novo preço.
- reduce: calcule o valor total do estoque
(
preco × estoque) de todos os produtos.
Desafio: usando encadeamento, calcule o valor total apenas dos produtos disponíveis em estoque.
Exercício 4 – Funções que retornam funções (closure)
Crie uma função criarSaudacao que receba um idioma
("pt", "en" ou "es") e retorne
uma função que, ao receber um nome, exiba a saudação no idioma correto.
Exemplo:
const saudarEmPortugues = criarSaudacao("pt");
const saudarEmIngles = criarSaudacao("en");
saudarEmPortugues("Ana"); // Olá, Ana!
saudarEmIngles("Ana"); // Hello, Ana!
Exercício 5 – Pipeline de dados (desafio)
Crie um array com pelo menos 6 objetos de estudantes
(nome, nota, turma). Em seguida, usando encadeamento de
filter, map e reduce:
- Filtre apenas os estudantes da turma
"ECO". - Filtre entre esses apenas os aprovados (nota ≥ 6).
- Use
mappara extrair só os nomes. - Use
reducepara construir uma string final no formato:
"Aprovados da turma ECO: Ana, Maria, Pedro"
Dica: cada método retorna um array, então você pode chamar o próximo diretamente encadeado.
Roteiro de estudo para quem faltou
- Leia as seções 1, 2 e 3 com atenção e reproduza cada exemplo em um arquivo
funcoes.js, executando comnode funcoes.jsou no console do navegador (F12). - Modifique os exemplos: troque valores, adicione parâmetros, reescreva funções tradicionais como arrow functions.
- Leia a seção 4 (Callbacks) com cuidado — é o conceito mais novo e será base para as próximas unidades.
- Resolva os exercícios 1 a 4. O exercício 5 é desafio opcional.
- Anote dúvidas para discutirmos na próxima aula.