Declaração de Funções (Function Declaration)
A declaração de função é a forma mais tradicional e direta de criar uma função em JavaScript. Você utiliza a palavra-chave function, seguida do nome, parâmetros entre parênteses e o corpo entre chaves. Essa forma é amplamente usada em código legado e continua sendo excelente para funções de escopo global ou para quando você precisa de hoisting.
function calcularDesconto(preco, percentual) {
const desconto = preco * (percentual / 100);
return preco - desconto;
}
console.log(calcularDesconto(100, 20)); // 80
Em ambiente de produção, essa abordagem é útil quando você precisa que a função seja acessível antes de sua declaração no código — graças ao hoisting. Porém, evite depender disso; é melhor manter código organizado e legível.
Expressões de Funções e Arrow Functions
Expressão de Função (Function Expression)
Aqui você atribui uma função a uma variável. Diferentemente da declaração, essa função não sofre hoisting de forma total — apenas a variável é hoisted, não seu conteúdo.
const calcularIMC = function(peso, altura) {
return peso / (altura * altura);
};
console.log(calcularIMC(70, 1.75)); // ~22.86
Arrow Functions (ES6)
Introduzidas em 2015, as arrow functions oferecem sintaxe concisa e binding léxico de this. São a escolha moderna padrão para código de produção.
// Múltiplos parâmetros
const saudacao = (nome, sobrenome) => {
return `Olá, ${nome} ${sobrenome}!`;
};
// Um parâmetro (parênteses opcionais)
const dobro = x => x * 2;
// Sem parâmetros
const getId = () => Math.random();
console.log(saudacao('João', 'Silva')); // Olá, João Silva!
console.log(dobro(5)); // 10
Dica importante: Arrow functions não têm seu próprio this. Isso é crucial em callbacks e métodos de objeto — use expressões de função tradicionais se precisar de this dinâmico.
const usuario = {
nome: 'Maria',
// ❌ Errado: this será undefined ou window
apresentarErrado: () => console.log(this.nome),
// ✅ Correto: this refere-se ao objeto
apresentarCorreto: function() { console.log(this.nome); }
};
usuario.apresentarCorreto(); // Maria
Hoisting: Como JavaScript Trata Funções
Hoisting é o comportamento onde JavaScript "move" declarações de função e variáveis para o topo de seu escopo durante a compilação. Entender isso é crítico para evitar bugs em produção.
Comportamento por Tipo de Função
Function Declaration: Completamente hoisted. Você pode chamar a função antes dela ser declarada.
console.log(somar(2, 3)); // 5 — funciona!
function somar(a, b) {
return a + b;
}
Function Expression e Arrow Functions: Apenas a variável é hoisted, não a função. Chamá-la antes da declaração resulta em erro.
console.log(multiplicar(2, 3)); // ❌ TypeError: multiplicar is not a function
const multiplicar = (a, b) => a * b;
Variáveis var: São hoisted, mas inicializadas como undefined. Com let e const, há hoisting mas há o "Temporal Dead Zone" — acesso antes da declaração causa erro.
console.log(x); // undefined
var x = 5;
console.log(y); // ❌ ReferenceError: Cannot access 'y' before initialization
let y = 10;
Boas práticas: Sempre declare funções antes de usá-las, independente do tipo. Use
constcom arrow functions — é mais seguro e torna o código previsível.
Funções em Produção: Padrões e Boas Práticas
Em código de produção real, você não escolhe um tipo de função apenas por sintaxe — contexto importa. Aqui estão padrões que realmente funcionam:
Callbacks e Promises: Arrow functions são ideais porque evitam problemas com this.
fetch('/api/usuarios')
.then(res => res.json())
.then(dados => console.log(dados))
.catch(erro => console.error('Erro:', erro));
Funções Construtoras e Métodos de Classe: Use expressões de função tradicional ou métodos de classe.
class Usuario {
constructor(nome) {
this.nome = nome;
}
saudar() {
return `Olá, sou ${this.nome}`;
}
// Não use arrow aqui se precisar de 'this'
}
const user = new Usuario('Pedro');
console.log(user.saudar()); // Olá, sou Pedro
Funções Puras e Utilitários: Arrow functions são perfeitas.
const filtrarPares = (numeros) => numeros.filter(n => n % 2 === 0);
const mapearIds = (usuarios) => usuarios.map(u => u.id);
console.log(filtrarPares([1, 2, 3, 4])); // [2, 4]
Evite Confusão de Hoisting: Em projetos grandes, erros de hoisting são silenciosos e perigosos. Mantenha consistência: declare antes de usar, use const por padrão.
Conclusão
Dominar funções em JavaScript é fundamental para escrever código profissional. Resumindo o aprendizado: (1) Use const com arrow functions como padrão em código moderno — sintaxe clara, this previsível, sem surpresas de hoisting. (2) Entenda hoisting completamente: declarações são hoisted, expressões não; let e const são seguros; var causa caos. (3) Escolha o tipo de função conforme o contexto: callbacks, promises e utilidades ganham com arrow functions; métodos e construtores se beneficiam de expressões tradicionais. Esses três pilares, aliados ao código organizado e consistente, levam você a produção confiável.