Bucle for
Introducción
El bucle for es una de las estructuras de control más utilizadas en JavaScript y en la programación en general. A diferencia de los bucles while y do-while, que se centran en repetir código mientras se cumpla una condición, el bucle for está diseñado especialmente para situaciones donde conocemos de antemano el número de iteraciones o necesitamos recorrer secuencias ordenadas de elementos. Su sintaxis compacta y expresiva permite crear iteraciones controladas con precisión, lo que lo convierte en una herramienta fundamental para cualquier programador. En este artículo, exploraremos en detalle el funcionamiento del bucle for, sus componentes y los diferentes patrones de implementación.
Sintaxis y componentes del bucle for
La sintaxis básica del bucle for se compone de tres partes principales separadas por punto y coma, todas contenidas dentro de paréntesis:
for (inicialización; condición; expresión_final) {
// Código a ejecutar en cada iteración
}
Cada uno de estos componentes tiene una función específica:
-
Inicialización: Se ejecuta una sola vez al principio. Generalmente se utiliza para declarar e inicializar una variable de control (contador).
-
Condición: Se evalúa antes de cada iteración. Si es verdadera (
true), se ejecuta el bloque de código; si es falsa (false), el bucle termina. -
Expresión final: Se ejecuta al final de cada iteración, después del bloque de código. Normalmente se utiliza para modificar la variable de control.
Veamos un ejemplo básico:
for (let i = 0; i < 5; i++) {
console.log(`Iteración número: ${i}`);
}
La salida de este código sería:
Iteración número: 0
Iteración número: 1
Iteración número: 2
Iteración número: 3
Iteración número: 4
En este ejemplo:
- Inicialización:
let i = 0- Creamos una variableicon valor inicial 0 - Condición:
i < 5- El bucle continuará mientrasisea menor que 5 - Expresión final:
i++- Incrementamosien 1 después de cada iteración
El flujo de ejecución es el siguiente:
- Se ejecuta la inicialización (
let i = 0) - Se evalúa la condición (
i < 5). Como es verdadera, se ejecuta el bloque de código. - Después de ejecutar el bloque, se ejecuta la expresión final (
i++) - Se vuelve a evaluar la condición, y el proceso se repite hasta que la condición sea falsa.
Inicialización, condición y expresión final
Vamos a analizar cada componente con más detalle:
Inicialización
La inicialización se ejecuta una única vez al comienzo del bucle. Aunque normalmente se usa para declarar e inicializar una variable contadora, puede tener diferentes formas:
// Variable declarada e inicializada en el bucle
for (let i = 0; i < 5; i++) {
console.log(i);
}
// Variable declarada fuera del bucle
let j;
for (j = 0; j < 5; j++) {
console.log(j);
}
// Múltiples variables inicializadas
for (let i = 0, j = 10; i < 5; i++, j--) {
console.log(`i = ${i}, j = ${j}`);
}
// Sin inicialización (usando punto y coma)
let k = 0;
for (; k < 5; k++) {
console.log(k);
}
Condición
La condición se evalúa antes de cada iteración:
// Condición simple
for (let i = 0; i < 5; i++) {
console.log(i);
}
// Condición más compleja
for (let i = 0; i * i < 25; i++) {
console.log(i); // Muestra 0, 1, 2, 3, 4
}
// Sin condición (bucle infinito si no hay break)
for (let i = 0; ; i++) {
console.log(i);
if (i >= 5) break; // Necesario para evitar bucle infinito
}
Expresión final
La expresión final se ejecuta después de cada iteración:
// Incremento simple
for (let i = 0; i < 5; i++) {
console.log(i);
}
// Decremento
for (let i = 5; i > 0; i--) {
console.log(i); // Cuenta regresiva: 5, 4, 3, 2, 1
}
// Incremento diferente
for (let i = 0; i < 10; i += 2) {
console.log(i); // Muestra números pares: 0, 2, 4, 6, 8
}
// Múltiples operaciones
for (let i = 0, j = 5; i < 5; i++, j--) {
console.log(`i: ${i}, j: ${j}`);
}
// Sin expresión final (actualizando dentro del bucle)
for (let i = 0; i < 5;) {
console.log(i);
i++; // Incremento dentro del bloque
}
Variantes de implementación
El bucle for es muy flexible y puede implementarse de diversas formas para adaptarse a diferentes necesidades:
Bucle for sin alguno de sus componentes
Todos los componentes del bucle for son opcionales, aunque debemos mantener los punto y coma:
// Sin inicialización
let i = 0;
for (; i < 5; i++) {
console.log(i);
}
// Sin condición (requiere break)
for (let i = 0; ; i++) {
console.log(i);
if (i >= 5) break;
}
// Sin expresión final
for (let i = 0; i < 5;) {
console.log(i);
i++; // Incremento dentro del bucle
}
// Solo con punto y coma (bucle infinito si no hay break)
let j = 0;
for (;;) {
console.log(j++);
if (j >= 5) break;
}
Bucle for con múltiples variables
Podemos inicializar y manipular múltiples variables:
// Incrementar una variable y decrementar otra
for (let i = 0, j = 10; i < 5; i++, j--) {
console.log(`i: ${i}, j: ${j}`);
}
// Salida:
// i: 0, j: 10
// i: 1, j: 9
// i: 2, j: 8
// i: 3, j: 7
// i: 4, j: 6
Bucle for con cuerpo vacío
En algunos casos, todo el trabajo se puede hacer en los componentes del bucle:
// Sumar números del 1 al 10
let suma = 0;
for (let i = 1; i <= 10; suma += i, i++);
console.log(suma); // Muestra: 55
Nota: Este estilo no es recomendable porque puede reducir la legibilidad del código.
Iteración sobre secuencias numéricas
Una de las aplicaciones más comunes del bucle for es iterar sobre secuencias numéricas:
Iteración ascendente
// Números del 1 al 5
for (let i = 1; i <= 5; i++) {
console.log(i);
}
// Muestra: 1, 2, 3, 4, 5
Iteración descendente
// Cuenta regresiva de 5 a 1
for (let i = 5; i >= 1; i--) {
console.log(i);
}
// Muestra: 5, 4, 3, 2, 1
Saltos en la iteración
// Números pares del 0 al 10
for (let i = 0; i <= 10; i += 2) {
console.log(i);
}
// Muestra: 0, 2, 4, 6, 8, 10
// Múltiplos de 5 hasta 50
for (let i = 5; i <= 50; i += 5) {
console.log(i);
}
// Muestra: 5, 10, 15, 20, 25, 30, 35, 40, 45, 50
Control de flujo dentro del bucle
Dentro de un bucle for, podemos utilizar las sentencias break y continue para controlar el flujo de ejecución:
break
La sentencia break termina la ejecución del bucle completo:
// Salir del bucle cuando se encuentra un número divisible por 7
for (let i = 1; i <= 20; i++) {
if (i % 7 === 0) {
console.log(`¡Encontrado! ${i} es divisible por 7`);
break; // Sale del bucle inmediatamente
}
console.log(`Verificando número ${i}`);
}
continue
La sentencia continue salta a la siguiente iteración, omitiendo el resto del código para la iteración actual:
// Mostrar solo números impares
for (let i = 1; i <= 10; i++) {
if (i % 2 === 0) {
continue; // Salta a la siguiente iteración si es par
}
console.log(`Número impar: ${i}`);
}
// Muestra: 1, 3, 5, 7, 9
Comparación con otros bucles
Cada tipo de bucle en JavaScript tiene sus propias características que lo hacen más adecuado para ciertas situaciones:
for vs while
// Usando for
for (let i = 0; i < 5; i++) {
console.log(i);
}
// Equivalente usando while
let i = 0;
while (i < 5) {
console.log(i);
i++;
}
El bucle for es generalmente más apropiado cuando:
- Conocemos el número exacto de iteraciones
- Necesitamos una variable de control con un valor inicial y un paso de incremento/decremento definido
- Queremos mantener la lógica de iteración en una sola línea
El bucle while es más adecuado cuando:
- No sabemos cuántas iteraciones necesitaremos
- La condición de salida depende de factores que pueden cambiar dentro del bucle
- La lógica para continuar o terminar el bucle es más compleja
for vs for...of
JavaScript también ofrece el bucle for...of para iterar sobre elementos de colecciones:
const numeros = [10, 20, 30, 40, 50];
// Usando for con índices
for (let i = 0; i < numeros.length; i++) {
console.log(numeros[i]);
}
// Usando for...of
for (const numero of numeros) {
console.log(numero);
}
El bucle for tradicional es mejor cuando:
- Necesitas el índice del elemento
- Quieres modificar los elementos del array
- Necesitas un control preciso sobre las iteraciones (saltar elementos, recorrer en orden inverso, etc.)
El bucle for...of es mejor cuando:
- Solo necesitas acceder a los valores, no a sus índices
- Quieres un código más limpio y legible
- Trabajas con estructuras iterables (arrays, strings, maps, sets, etc.)
Patrones comunes y buenas prácticas
Iteración sobre arrays
const frutas = ["manzana", "naranja", "plátano", "fresa", "kiwi"];
// Recorrer todos los elementos
for (let i = 0; i < frutas.length; i++) {
console.log(`Fruta ${i+1}: ${frutas[i]}`);
}
// Recorrer en orden inverso
for (let i = frutas.length - 1; i >= 0; i--) {
console.log(`Fruta (orden inverso) ${frutas.length - i}: ${frutas[i]}`);
}
Generación de patrones
// Generar un triángulo de asteriscos
let triangulo = "";
const altura = 5;
for (let i = 1; i <= altura; i++) {
let linea = "";
for (let j = 1; j <= i; j++) {
linea += "* ";
}
triangulo += linea + "\n";
}
console.log(triangulo);
/*
*
* *
* * *
* * * *
* * * * *
*/
Procesamiento de datos
const temperaturas = [22, 19, 25, 30, 28, 24, 27];
let suma = 0;
let maxima = temperaturas[0];
let minima = temperaturas[0];
for (let i = 0; i < temperaturas.length; i++) {
const temp = temperaturas[i];
suma += temp;
if (temp > maxima) {
maxima = temp;
}
if (temp < minima) {
minima = temp;
}
}
const media = suma / temperaturas.length;
console.log(`Temperatura media: ${media.toFixed(1)}°C`);
console.log(`Temperatura máxima: ${maxima}°C`);
console.log(`Temperatura mínima: ${minima}°C`);
Optimización del bucle
const elementos = ["a", "b", "c", "d", "e"];
// Menos eficiente (recalcula length en cada iteración)
for (let i = 0; i < elementos.length; i++) {
console.log(elementos[i]);
}
// Más eficiente (calcula length una sola vez)
for (let i = 0, len = elementos.length; i < len; i++) {
console.log(elementos[i]);
}
Bucles for anidados
// Tabla de multiplicar
for (let i = 1; i <= 5; i++) {
for (let j = 1; j <= 5; j++) {
console.log(`${i} x ${j} = ${i * j}`);
}
console.log("-----------");
}
Ejemplos prácticos
Ejemplo 1: Cálculo de factorial
function calcularFactorial(n) {
if (n < 0) return "No existe el factorial de números negativos";
let factorial = 1;
// Usando bucle for
for (let i = 2; i <= n; i++) {
factorial *= i;
}
return factorial;
}
console.log(calcularFactorial(5)); // Muestra: 120
Ejemplo 2: Generar secuencia Fibonacci
function generarFibonacci(n) {
if (n <= 0) return [];
if (n === 1) return [0];
const secuencia = [0, 1];
for (let i = 2; i < n; i++) {
const siguienteNumero = secuencia[i - 1] + secuencia[i - 2];
secuencia.push(siguienteNumero);
}
return secuencia;
}
console.log(generarFibonacci(10));
// Muestra: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Ejemplo 3: Verificar si un número es primo
function esPrimo(numero) {
if (numero <= 1) return false;
if (numero <= 3) return true;
if (numero % 2 === 0 || numero % 3 === 0) return false;
// Comprobamos divisores desde 5 hasta la raíz cuadrada del número
for (let i = 5; i * i <= numero; i += 6) {
if (numero % i === 0 || numero % (i + 2) === 0) {
return false;
}
}
return true;
}
// Mostrar números primos del 1 al 50
for (let i = 1; i <= 50; i++) {
if (esPrimo(i)) {
console.log(`${i} es un número primo`);
}
}
Ejemplo 4: Filtrado de elementos de un array
function filtrarNumerosPares(numeros) {
const pares = [];
for (let i = 0; i < numeros.length; i++) {
if (numeros[i] % 2 === 0) {
pares.push(numeros[i]);
}
}
return pares;
}
const listaNumeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
console.log(filtrarNumerosPares(listaNumeros));
// Muestra: [2, 4, 6, 8, 10]
Ejemplo 5: Buscar el índice de un elemento
function buscarIndice(array, elemento) {
for (let i = 0; i < array.length; i++) {
if (array[i] === elemento) {
return i;
}
}
return -1; // No encontrado
}
const frutas = ["manzana", "naranja", "plátano", "fresa"];
console.log(buscarIndice(frutas, "plátano")); // Muestra: 2
console.log(buscarIndice(frutas, "kiwi")); // Muestra: -1
Resumen
El bucle for es una estructura de control versátil y potente en JavaScript que nos permite ejecutar código repetidamente con un control preciso sobre el número de iteraciones. Su estructura organizada en tres componentes (inicialización, condición y expresión final) lo hace especialmente adecuado para casos donde conocemos de antemano el número de repeticiones o necesitamos iterar sobre secuencias de elementos.
Hemos visto cómo funciona la sintaxis básica del bucle for, sus diversas variantes y cómo podemos controlar su flujo mediante sentencias como break y continue. También hemos analizado las diferencias con otros tipos de bucles y cuándo es más apropiado usar cada uno.
Entre las aplicaciones más comunes del bucle for se encuentran la iteración sobre arrays, la generación de patrones, el procesamiento de datos y la implementación de algoritmos. Su flexibilidad y expresividad lo convierten en una herramienta esencial en el arsenal de cualquier programador de JavaScript.
Aunque existen alternativas más modernas como forEach, map, filter y otros métodos de array para ciertos casos específicos, el bucle for clásico sigue siendo fundamental por su rendimiento, su versatilidad y el control preciso que ofrece sobre las iteraciones.