Skip to content

Funciones ​

Las funciones son el corazón de JavaScript. Te permiten empaquetar un conjunto de instrucciones, darle un nombre y reutilizarlo cuantas veces quieras. Calcular el IVA, validar un correo, mostrar un producto en pantalla: todo eso se convierte en funciones. En esta lección aprenderás las tres formas de crearlas, cómo pasarles datos, cómo devolver resultados y qué son los callbacks y las funciones puras.

Concepto ​

Una función es como una receta de cocina:

  • Tiene un nombre: "Agua de horchata".
  • Recibe ingredientes (parámetros): arroz, canela, azúcar.
  • Sigue pasos (el cuerpo de la función).
  • Entrega un resultado (el valor de retorno): una jarra de agua.

Escribes la receta una vez y la preparas (la llamas) cuando quieras, con distintos ingredientes.

js
//        nombre      parámetros
function calcularIVA(precio) {
  return precio * 0.16;  // resultado
}

calcularIVA(100);  // llamada → 16
calcularIVA(250);  // llamada → 40

¿Por qué usar funciones?

  • Reutilizar: escribes la lógica una vez.
  • Organizar: divides un problema grande en piezas pequeñas.
  • Mantener: si cambia el IVA, lo corriges en un solo lugar.
  • Leer mejor: aplicarDescuento(total) se entiende mejor que cinco líneas de cálculos.

Tres formas de crear funciones ​

1. Declaración de función ​

js
function saludar(nombre) {
  return `Hola, ${nombre}`;
}

console.log(saludar('Ana')); // "Hola, Ana"

Las declaraciones tienen hoisting completo: puedes llamarlas incluso antes de la línea donde las escribiste.

js
console.log(sumar(2, 3)); // 5 ✅ funciona

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

2. Expresión de función ​

Guardas una función (normalmente anónima) en una variable:

js
const despedir = function (nombre) {
  return `Hasta luego, ${nombre}`;
};

console.log(despedir('Luis')); // "Hasta luego, Luis"

Aquí no hay hoisting útil: si la llamas antes de definirla, obtienes un error (por la TDZ de const, que viste en Variables y tipos).

3. Funciones flecha (arrow functions) ​

La sintaxis moderna y compacta (ES6):

js
// Forma completa
const multiplicar = (a, b) => {
  return a * b;
};

// Si sólo devuelve una expresión, puedes omitir llaves y return
const multiplicarCorto = (a, b) => a * b;

// Con un solo parámetro, los paréntesis son opcionales
const doble = n => n * 2;

// Sin parámetros, paréntesis vacíos
const obtenerFecha = () => new Date().toLocaleDateString('es-MX');

// Para devolver un objeto directamente, envuélvelo en paréntesis
const crearProducto = (nombre, precio) => ({ nombre, precio });

console.log(multiplicarCorto(4, 5)); // 20
console.log(doble(8));               // 16
console.log(crearProducto('Taza', 120)); // { nombre: 'Taza', precio: 120 }

¿Cuál uso?

  • Declaraciones (function nombre()): para funciones principales de tu programa.
  • Flechas: para funciones cortas y callbacks (lo más común en código moderno).

Las flechas tienen una diferencia técnica con this que verás en POO y clases. Por ahora, ambas te sirven igual.

Parámetros y argumentos ​

  • Parámetros: los nombres que pones al definir la función (precio, cantidad).
  • Argumentos: los valores reales que pasas al llamarla (250, 3).
js
function calcularSubtotal(precio, cantidad) { // parámetros
  return precio * cantidad;
}

calcularSubtotal(250, 3); // argumentos → 750

Si pasas menos argumentos, los que faltan valen undefined:

js
calcularSubtotal(250); // 250 * undefined → NaN

Parámetros por defecto ​

js
function calcularSubtotal(precio, cantidad = 1) {
  return precio * cantidad;
}

calcularSubtotal(250);    // 250 (cantidad = 1)
calcularSubtotal(250, 4); // 1000

// Pueden depender de parámetros anteriores
function crearUsuario(nombre, rol = 'cliente', saludo = `Bienvenido, ${nombre}`) {
  return { nombre, rol, saludo };
}
console.log(crearUsuario('Sofía'));
// { nombre: 'Sofía', rol: 'cliente', saludo: 'Bienvenido, Sofía' }

Parámetros rest (...) ​

Para recibir cualquier cantidad de argumentos como un array:

js
function sumarTodo(...numeros) {
  let total = 0;
  for (const n of numeros) {
    total += n;
  }
  return total;
}

console.log(sumarTodo(10, 20));          // 30
console.log(sumarTodo(5, 15, 25, 35));   // 80

// Se pueden combinar con parámetros normales (rest siempre al final)
function registrarPedido(cliente, ...productos) {
  console.log(`${cliente} pidió ${productos.length} productos:`, productos);
}
registrarPedido('Ana', 'Café', 'Pan', 'Jugo');

return: devolver resultados ​

return hace dos cosas: entrega un valor y termina la función inmediatamente.

js
function obtenerDescuento(total) {
  if (total >= 2000) return 0.10;  // sale aquí si se cumple
  if (total >= 1000) return 0.05;
  return 0;                         // valor por defecto
}

const descuento = obtenerDescuento(1500); // 0.05

Si una función no tiene return, devuelve undefined:

js
function saludar(nombre) {
  console.log(`Hola, ${nombre}`); // imprime, pero no devuelve
}

const resultado = saludar('Ana'); // imprime "Hola, Ana"
console.log(resultado);           // undefined

Error común

Confundir imprimir con devolver. console.log sólo muestra algo en la consola; no te da el valor para seguir usándolo. Si necesitas el resultado para otro cálculo, usa return.

js
// ❌
function calcularTotal(precio) {
  console.log(precio * 1.16);
}
const total = calcularTotal(100); // undefined

// ✅
function calcularTotalBien(precio) {
  return precio * 1.16;
}
const totalBien = calcularTotalBien(100); // 116

Callbacks: funciones como argumentos ​

En JavaScript las funciones son valores: puedes guardarlas en variables, meterlas en arrays y pasarlas a otras funciones. Una función que se pasa como argumento se llama callback.

js
// Una función que recibe otra función
function procesarPedido(pedido, alTerminar) {
  console.log(`Procesando pedido #${pedido}...`);
  alTerminar(pedido); // llamamos al callback
}

function enviarCorreo(id) {
  console.log(`📧 Correo de confirmación enviado para el pedido #${id}`);
}

procesarPedido(1024, enviarCorreo);
// Procesando pedido #1024...
// 📧 Correo de confirmación enviado para el pedido #1024

// También se puede pasar una función flecha directamente
procesarPedido(1025, (id) => console.log(`Pedido ${id} listo`));

Usarás callbacks todo el tiempo:

js
// Eventos: "cuando hagan clic, ejecuta esta función"
boton.addEventListener('click', () => {
  console.log('¡Clic!');
});

// Temporizadores: "en 2 segundos, ejecuta esto"
setTimeout(() => {
  console.log('Pasaron 2 segundos');
}, 2000);

// Métodos de arrays: "para cada producto, haz esto"
const precios = [100, 200, 300];
const conIVA = precios.map((precio) => precio * 1.16);
console.log(conIVA); // [116, 232, 348]

Error común

Llamar al callback en lugar de pasarlo:

js
// ❌ Ejecuta saludar AHORA y pasa su resultado (undefined)
boton.addEventListener('click', saludar());

// ✅ Pasa la función para que se ejecute DESPUÉS
boton.addEventListener('click', saludar);

Funciones puras ​

Una función es pura cuando:

  1. Con los mismos argumentos, siempre devuelve el mismo resultado.
  2. No modifica nada fuera de ella (no tiene efectos secundarios).
js
// ✅ Pura: sólo depende de sus parámetros
function aplicarDescuento(precio, porcentaje) {
  return precio - precio * (porcentaje / 100);
}

// ❌ Impura: depende y modifica una variable externa
let total = 0;
function agregarAlTotal(precio) {
  total += precio; // efecto secundario
  return total;
}

// ❌ Impura: modifica el array que recibe
function agregarProducto(carrito, producto) {
  carrito.push(producto);
  return carrito;
}

// ✅ Versión pura: devuelve un array NUEVO
function agregarProductoPuro(carrito, producto) {
  return [...carrito, producto];
}

Las funciones puras son más fáciles de probar, depurar y reutilizar. No todo puede ser puro (mostrar algo en pantalla o guardar datos son efectos secundarios necesarios), pero procura que la lógica de cálculo sí lo sea.

Buena práctica

  • Una función debe hacer una sola cosa y hacerla bien.
  • Nombra las funciones con verbos: calcularTotal, validarEmail, mostrarProductos.
  • Si una función pasa de ~20–30 líneas, probablemente puedes dividirla.
  • Separa la lógica (funciones puras que calculan) de la interfaz (funciones que tocan el DOM).

Ejemplo completo: carrito sencillo ​

js
// Lógica pura: calcula, no toca nada externo
const calcularSubtotal = (productos) => {
  let suma = 0;
  for (const p of productos) {
    suma += p.precio * p.cantidad;
  }
  return suma;
};

const calcularEnvio = (subtotal, envioGratisDesde = 999) =>
  subtotal >= envioGratisDesde ? 0 : 99;

const formatearPrecio = (cantidad) => `$${cantidad.toFixed(2)} MXN`;

// Función que orquesta todo
function resumenCarrito(productos) {
  const subtotal = calcularSubtotal(productos);
  const envio = calcularEnvio(subtotal);
  const total = subtotal + envio;

  return {
    subtotal: formatearPrecio(subtotal),
    envio: envio === 0 ? 'Gratis' : formatearPrecio(envio),
    total: formatearPrecio(total),
  };
}

const carrito = [
  { nombre: 'Playera', precio: 250, cantidad: 2 },
  { nombre: 'Gorra', precio: 180, cantidad: 1 },
];

console.log(resumenCarrito(carrito));
// { subtotal: '$680.00 MXN', envio: '$99.00 MXN', total: '$779.00 MXN' }

Ejercicios ​

  1. Crea una función flecha celsiusAFahrenheit(c) que devuelva la conversión (c * 9 / 5 + 32).
  2. Crea crearSaludo(nombre, idioma = 'es') que devuelva 'Hola, X' en español o 'Hello, X' en inglés.
  3. Crea promedio(...calificaciones) que reciba cualquier cantidad de números y devuelva su promedio. Si no recibe ninguno, debe devolver 0.
  4. Crea repetir(veces, accion) que ejecute el callback accion la cantidad de veces indicada, pasándole el número de vuelta.
Ver solución

1.

js
const celsiusAFahrenheit = (c) => c * 9 / 5 + 32;
console.log(celsiusAFahrenheit(30)); // 86

2.

js
function crearSaludo(nombre, idioma = 'es') {
  return idioma === 'en' ? `Hello, ${nombre}` : `Hola, ${nombre}`;
}
console.log(crearSaludo('Ana'));       // "Hola, Ana"
console.log(crearSaludo('Ana', 'en')); // "Hello, Ana"

3.

js
function promedio(...calificaciones) {
  if (calificaciones.length === 0) return 0;

  let suma = 0;
  for (const c of calificaciones) {
    suma += c;
  }
  return suma / calificaciones.length;
}
console.log(promedio(8, 9, 10)); // 9
console.log(promedio());         // 0

4.

js
function repetir(veces, accion) {
  for (let i = 1; i <= veces; i++) {
    accion(i);
  }
}

repetir(3, (n) => console.log(`Vuelta ${n}`));
// Vuelta 1
// Vuelta 2
// Vuelta 3

Resumen ​

  • Una función agrupa instrucciones reutilizables; se define una vez y se llama muchas veces.
  • Tres formas: declaración (con hoisting), expresión y flecha (compacta, ideal para callbacks).
  • Los parámetros por defecto evitan undefined; los rest (...) reciben muchos argumentos como array.
  • return devuelve un valor y termina la función; sin return, devuelve undefined.
  • Un callback es una función que pasas a otra para que la ejecute después.
  • Las funciones puras no tienen efectos secundarios y siempre dan el mismo resultado.

Siguiente: Scope y closures

Academia Web — aprende, copia y construye.