Fundamentos de Funções em JavaScript

Introdução às Funções em JavaScript

As funções são blocos de construção essenciais em JavaScript, permitindo agrupar um conjunto de instruções para executar uma tarefa específica. Elas promovem a reutilização de código e a organização lógica, tornando seus programas mais modulares e fáceis de manter.

Declaração e Invocação de Funções

Para utilizar uma função, primeiramente é preciso declará-la e, em seguida, invocá-la (chamá-la). Uma função declarada por si só não executa seu código; ela precisa ser explicitamente chamada.


<script>
 // 1. Declaração de uma função nomeada
 function exibirMensagem() {
   console.log("Olá do mundo das funções!");
 }

 // 2. Invocação da função
 // O código dentro da função só será executado quando ela for chamada.
 exibirMensagem(); // Saída: Olá do mundo das funções!
</script>
 

Exemplo Prático: Agrupando Lógica

Considere uma tarefa repetitiva, como calcular a soma de uma sequência de números. Em vez de duplicar o código sempre que precisar fazer isso, podemos encapsular a lógica em uma função.


<script>
 // Função para calcular a soma dos números de 1 a 100
 function calcularSomaCem() {
   let acumulador = 0;
   for (let i = 1; i <= 100; i++) {
     acumulador += i;
   }
   console.log("A soma de 1 a 100 é:", acumulador);
 }

 // Chamando a função para ver o resultado
 calcularSomaCem(); // Saída: A soma de 1 a 100 é: 5050
</script>
 

Parâmetros de Função

Para tornar as funções mais flexíveis, podemos passar informações para elas através de parâmetros. Esses valores são conhecidos como argumentos quando a função é chamada.

  • Parâmetros Formais: Nomes listados na definição da função (ex: inicio, fim).
  • Argumentos Reais: Os valores que são passados para a função quando ela é invocada (ex: 1, 100).

<script>
 // 'inicio' e 'fim' são parâmetros formais
 function somarIntervalo(inicio, fim) {
   let total = 0;
   for (let i = inicio; i <= fim; i++) {
     total += i;
   }
   console.log(`A soma entre ${inicio} e ${fim} é: ${total}`);
 }

 // Invocando a função com argumentos reais
 somarIntervalo(1, 100);   // Saída: A soma entre 1 e 100 é: 5050
 somarIntervalo(50, 150);  // Saída: A soma entre 50 e 150 é: 10100
</script>
 

Valores Padrão para Parâmetros

A partir do ES6, é possível definir valores padrão para os parâmetros de uma função. Se um argumento não for fornecido para um parâmetro com valor padrão, ele assumirá esse valor automaticamente, evitando resultados inesperados como NaN.


<script>
 function somarDoisNumeros(numA = 0, numB = 0) {
   console.log(numA + numB);
 }

 somarDoisNumeros(5, 7); // Saída: 12
 somarDoisNumeros(10);   // Saída: 10 (numB usa o valor padrão 0)
 somarDoisNumeros();     // Saída: 0 (ambos usam seus valores padrão 0)
</script>
 

Cálculo da Soma de Elementos em um Array

Funções podem ser usadas para processar estruturas de dados, como arrays. Aqui, uma função calcula a soma de todos os elementos em um array numérico, com um valor padrão para o array para evitar erros.


<script>
 // Calcula a soma de todos os números em um array
 function somarElementosArray(colecao = []) {
   let somaTotal = 0;
   for (let i = 0; i < colecao.length; i++) {
     somaTotal += colecao[i];
   }
   console.log("A soma dos elementos do array é:", somaTotal);
 }

 somarElementosArray([10, 20, 30, 40]); // Saída: A soma dos elementos do array é: 100
 somarElementosArray([5, 15, 25]);     // Saída: A soma dos elementos do array é: 45
 somarElementosArray();                 // Saída: A soma dos elementos do array é: 0 (usa array vazio padrão)
</script>
 

Passando Variáveis como Argumentos

Os argumentos passados para uma função podem ser valores literais ou variáveis. Isso demonstra a flexibilidade de como as funções podem ser alimentadas com dados dinâmicos.


<script>
 function calcularPotencia(base, expoente) {
   let resultado = base ** expoente; // Operador de exponenciação
   console.log(`${base} elevado a ${expoente} é: ${resultado}`);
 }

 let meuNumero = 3;
 let meuExpoente = 4;

 // Variáveis são passadas como argumentos reais
 calcularPotencia(meuNumero, meuExpoente); // Saída: 3 elevado a 4 é: 81
 calcularPotencia(2, 8);                   // Saída: 2 elevado a 8 é: 256
</script>
 

Retorno de Valores de Funções

Muitas vezes, uma função precisa produzir um resultado que pode ser usado em outras partes do código. Isso é feito usando a instrução return. Quando return é executado, a função termina imediatamente e o valor espeicficado é "devolvido" ao local de onde a função foi chamada.


<script>
 // Função que retorna um valor simples
 function obterConstante() {
   return 42;
 }
 let valorRetornado = obterConstante();
 console.log("Valor retornado da função:", valorRetornado); // Saída: Valor retornado da função: 42

 // Função de soma que retorna o resultado
 function adicionar(a, b) {
   return a + b;
   console.log("Esta linha não será executada."); // Código após return não é alcançável
 }
 let somaResult = adicionar(15, 20);
 console.log("A soma é:", somaResult); // Saída: A soma é: 35

 // Funções sem 'return' explicitamente retornam 'undefined'
 function funcaoVazia() {
   // Não há instrução return
 }
 let resultadoVazio = funcaoVazia();
 console.log("Resultado de função sem return:", resultadoVazio); // Saída: Resultado de função sem return: undefined
</script>
 

Funções para Encontrar Valores Extremos em um Array

É comum precisar encontrar o maior ou menor valor em uma coleção. Uma função pode encapsular essa lógica e retornar o resultado.


<script>
 // Retorna o maior de dois números
 function encontrarMaior(val1, val2) {
   return val1 > val2 ? val1 : val2;
 }
 console.log("O maior entre 30 e 10 é:", encontrarMaior(30, 10)); // Saída: O maior entre 30 e 10 é: 30

 // Retorna o maior elemento de um array
 function obterMaximoArray(numeros = []) {
   if (numeros.length === 0) return undefined;
   let maximo = numeros[0];
   for (let i = 1; i < numeros.length; i++) {
     if (numeros[i] > maximo) {
       maximo = numeros[i];
     }
   }
   return maximo;
 }
 console.log("Máximo do array [7, 2, 9, 1]:", obterMaximoArray([7, 2, 9, 1])); // Saída: Máximo do array [7, 2, 9, 1]: 9

 // Retorna o maior e o menor elemento de um array como um novo array
 function obterExtremosArray(numeros = []) {
   if (numeros.length === 0) return [undefined, undefined];
   let maximo = numeros[0];
   let minimo = numeros[0];

   for (let i = 1; i < numeros.length; i++) {
     if (numeros[i] > maximo) {
       maximo = numeros[i];
     }
     if (numeros[i] < minimo) {
       minimo = numeros[i];
     }
   }
   return [maximo, minimo]; // Retorna um array com [maior, menor]
 }

 const valores = [22, 5, 87, 13, 4];
 const [valorMax, valorMin] = obterExtremosArray(valores); // Desestruturação de array para pegar os resultados
 console.log(`Array: [${valores}] -- Máximo: ${valorMax}, Mínimo: ${valorMin}`);
 // Saída: Array: [22,5,87,13,4] -- Máximo: 87, Mínimo: 4
</script>
 

Detalhes Importantes sobre Funções

Ao trabalhar com funções, é crucial entender alguns comportamentos:

  • Sobrescrita de Funções Declaradas: Se você declarar múltiplas funções com o mesmo nome no mesmo escopo (usando function declaration), a última declaração "vencerá" e substituirá as anteriores.
  • Comportamento com Parâmetros Incompatíveis:
    • Argumentos em excesso: Argumentos adicionais que não correspondem a nenhum parâmetro formal são simplesmente ignorados.
    • Argumentos insuficientes: Parâmetros formais para os quais não há argumento correspondente receberão o valor undefined. Isso pode levar a operações como número + undefined, resultando em NaN.

<script>
 // Exemplo de sobrescrita de função
 function dizerOla() {
   console.log("Primeiro Olá!");
 }
 function dizerOla() {
   console.log("Segundo Olá!"); // Esta declaração sobrescreve a primeira
 }
 dizerOla(); // Saída: Segundo Olá!

 // Exemplo de parâmetros
 function operarNumeros(param1, param2) {
   console.log(param1 + param2);
 }

 operarNumeros(10, 20, 30); // Saída: 30 (o '30' é ignorado)
 operarNumeros(5);         // Saída: NaN (5 + undefined = NaN)
</script>
 

Entendendo o Escopo em JavaScript

Escopo se refere à acessibilidade de variáveis, funções e objetos em diferentes partes do seu código. Em JavaScript, os principais tipos de escopo são:

  • Escopo Global: Variáveis declaradas fora de qualquer função são globais e podem ser acessadas de qualquer lugar no programa.
  • Escopo de Função (Local): Variáveis declaradas dentro de uma função são locais a essa função e só podem ser acessadas dentro dela.

<script>
 // Variável global
 let nomeGlobal = "Mundo";

 function saudarGlobal() {
   console.log("Olá, " + nomeGlobal + "!"); // Acessando variável global
 }
 saudarGlobal(); // Saída: Olá, Mundo!
 console.log(nomeGlobal); // Saída: Mundo

 function saudarLocal() {
   // Variável local à função saudarLocal
   let nomeLocal = "JavaScript";
   console.log("Olá, " + nomeLocal + "!");
 }
 saudarLocal(); // Saída: Olá, JavaScript!
 // console.log(nomeLocal); // Erro: nomeLocal is not defined (fora do escopo)
</script>
 

Casos Especiais de Variáveis e Escopo Léxico

O JavaScript utiliza um cnoceito chamado escopo léxico (ou estático), o que significa que o escopo de uma variável é determinado pela sua posição no código no momento da escrita. Funções aninhadas podem acessar variáveis do seu escopo pai.


<script>
 let valorExterno = 100; // Variável no escopo global

 function funcaoExterna() {
   let valorInterno = 50; // Variável no escopo da funcaoExterna

   function funcaoAninhada() {
     let valorMaisInterno = 20; // Variável no escopo da funcaoAninhada
     console.log(valorExterno);     // Acessa a variável global: 100
     console.log(valorInterno);     // Acessa a variável do escopo pai: 50
     console.log(valorMaisInterno); // Acessa sua própria variável: 20
   }
   funcaoAninhada();
 }
 funcaoExterna();
</script>
 

Funções Anônimas e Expressões de Função

Uma função anônima é uma função sem nome. Frequentemente, elas são atribuídas a variáveis, criando o que chamamos de expressão de função.


<script>
 // 1. Expressão de Função: a função é atribuída a uma variável
 const multiplicar = function(numX, numY) {
   console.log(numX * numY);
 };
 multiplicar(6, 7); // Saída: 42

 // Diferença em relação à declaração de função nomeada:
 // Funções nomeadas sofrem "hoisting" (podem ser chamadas antes de sua declaração).
 // Expressões de função NÃO sofrem hoisting completo; precisam ser declaradas antes de serem chamadas.
 // minhaOutraFuncao(); // Isso geraria um erro se fosse uma expressão de função
 function minhaOutraFuncao() {
   console.log("Sou uma função nomeada e fui 'hoisted'.");
 }
 minhaOutraFuncao(); // Saída: Sou uma função nomeada e fui 'hoisted'.
</script>
 

Funções Imediatamente Invocadas (IIFE - Immediately Invoked Function Expressions)

As IIFEs são expressões de função que são executadas assim que são definidas. Elas são úteis para criar um novo escopo de variável, isolando o código e evitando a poluição do escopo global.


<script>
 // Primeira sintaxe comum para IIFE
 (function() {
   let variavelIsolada = "Esta variável é local à IIFE.";
   console.log(variavelIsolada);
 })(); // Os parênteses finais invocam a função

 // Segunda sintaxe comum para IIFE (com argumentos)
 (function(paramA, paramB) {
   console.log(`A soma dentro da IIFE é: ${paramA + paramB}`);
 }(10, 5)); // Os parênteses externos englobam a função, os internos a invocam
</script>
 

Exemplo: Função de Conversão de Tempo

Uma aplicação prática de funções é a conversão de unidades. Por exemplo, converter um total de segundos em horas, minutos e segundos formatados.


<script>
 // Solicita ao usuário um número de segundos
 let totalSegundos = +prompt('Por favor, insira o número total de segundos:');

 // Função para converter segundos em formato HH:MM:SS
 function converterSegundosParaTempo(segundos) {
   const horas = Math.floor(segundos / 3600);      // 3600 segundos em uma hora
   const minutos = Math.floor((segundos % 3600) / 60); // Segundos restantes após horas, divididos por 60
   const segundosRestantes = segundos % 60; // Segundos restantes

   // Formata cada componente para ter dois dígitos (ex: 5 -> "05")
   const horasFormatadas = String(horas).padStart(2, '0');
   const minutosFormatados = String(minutos).padStart(2, '0');
   const segundosFormatados = String(segundosRestantes).padStart(2, '0');

   return `Tempo convertido: ${horasFormatadas}h ${minutosFormatados}m ${segundosFormatados}s`;
 }

 let tempoFormatado = converterSegundosParaTempo(totalSegundos);
 document.write(`<h3>${tempoFormatado}</h3>`);
</script>
 

Interrupção Lógica (Short-Circuiting)

Operadores lógicos && (AND) e || (OR) em JavaScript não apenas retornam true ou false, mas também o valor do último operando avaliado, com base em suas regras de "curto-circuito". Isso pode ser usado para fornecer valores padrão de forma concisa.

  • && (AND): Se o primeiro operando for falso, retorna o primeiro operando e não avalia o segundo. Se o primeiro for verdadeiro, retorna o segundo operando.
  • || (OR): Se o primeiro operando for verdadeiro, retorna o primeiro operando e não avalia o segundo. Se o primeiro for falso, retorna o segundo operando.

<script>
 let nivel = 5;
 console.log(false && nivel++); // Saída: false. nivel++ não é executado.
 console.log("Nível após false &&:", nivel); // Saída: Nível após false &&: 5

 let status = true;
 console.log(true || status++); // Saída: true. status++ não é executado.
 console.log("Status após true ||:", status); // Saída: Status após true ||: true

 // Uso de || para definir valores padrão (antes do ES6, ou para fallback)
 function processarValores(valorA, valorB) {
   valorA = valorA || 1; // Se valorA for 'falsy' (0, null, undefined, '', false), usa 1
   valorB = valorB || 1;
   console.log(`Processando: ${valorA} * ${valorB} = ${valorA * valorB}`);
 }

 processarValores(10, 2); // Saída: Processando: 10 * 2 = 20
 processarValores(null, 5); // Saída: Processando: 1 * 5 = 5 (null é 'falsy', usa 1)
 processarValores(0); // Saída: Processando: 1 * 1 = 1 (0 é 'falsy', ambos usam 1)
</script>
 

Tags: javascript funções escopo parâmetros ExpressõesDeFunção

Publicado em 8-13 23:15