JSON y forEach en JavaScript: guardar y recorrer datos con localStorage

Cómo convertir objetos a texto y de vuelta, recorrer arrays sin complicarte la vida y guardar datos que sobreviven a la recarga de página.

Llevas un rato con JavaScript y ya sabes crear variables, funciones, bucles. Pero en cuanto intentas guardar algo entre recarga y recarga, los datos desaparecen. O recibes información de una API y no entiendes por qué no puedes acceder a ella como si fuera un objeto normal.

El problema casi siempre es el mismo: no sabes cuándo tienes un objeto JavaScript y cuándo tienes texto con pinta de objeto. Esa confusión es exactamente lo que resuelven JSON y localStorage juntos.

En este tutorial vas a aprender JSON.stringify() y JSON.parse() para convertir datos, forEach() para recorrer listas, y cómo combinar todo en una lista de tareas que sobrevive a la recarga de página.

Qué es JSON

Cuando JavaScript trabaja con datos, los maneja como objetos: estructuras con propiedades a las que puedes acceder con un punto. Pero en cuanto necesitas guardar esos datos en algún sitio —un archivo, el navegador, un servidor— el problema es que los objetos JavaScript no se pueden almacenar directamente. Solo se puede guardar texto.

JSON es el formato de texto que resuelve eso. Toma tus objetos y los convierte en una cadena de caracteres que cualquier sistema entiende, independientemente del lenguaje. Cuando lo recibes de vuelta, lo conviertes otra vez a objeto. Eso es todo.

La confusión típica la primera vez que ves esto es pensar que JSON es un objeto. No lo es. Es texto con una estructura concreta. Si intentas acceder a sus propiedades sin convertirlo antes, obtienes undefined y no entiendes por qué.

JavaScript 📋
// Objeto JavaScript (solo en tu código)
const persona = {
  nombre: "Ana",
  edad: 25
};

// JSON (texto que se puede enviar/guardar/recibir)
'{"nombre":"Ana","edad":25}'

JSON.stringify(): de objeto a texto

Cada vez que necesitas sacar un objeto de JavaScript hacia el exterior —guardarlo en el navegador, mandarlo a un servidor, escribirlo en un archivo— tienes que convertirlo a texto primero. Para eso existe JSON.stringify().

El resultado es una cadena. No un objeto, no un array: texto plano que representa tu estructura de datos. A partir de ahí puedes guardarlo donde quieras.

JavaScript 📋
const misDatos = {
  usuario: "carlos",
  puntuacion: 150,
  nivel: 3
};

const datosEnTexto = JSON.stringify(misDatos);

console.log(datosEnTexto);
// '{"usuario":"carlos","puntuacion":150,"nivel":3}'

JSON.parse(): de texto a objeto

La operación inversa. Cuando tienes texto JSON —de localStorage, de una API, de donde sea— y quieres trabajar con él como objeto, usas JSON.parse().

Aquí es donde la mayoría se atasca la primera vez. Ves los datos en la consola y tienen toda la pinta de un objeto, pero cuando intentas acceder a una propiedad te devuelve undefined. El problema: sigues trabajando con el texto, no con el objeto. Falta el parse.

JavaScript — error típico y solución 📋
// ❌ MAL: intentar usar datos JSON como objeto
const textoJSON = '{"nombre":"Pedro"}';
console.log(textoJSON.nombre); // undefined — es texto, no objeto

// ✅ BIEN: convertir primero con JSON.parse()
const objeto = JSON.parse(textoJSON);
console.log(objeto.nombre); // "Pedro"
JavaScript 📋
const textoJSON = '{"nombre":"Laura","tareas":["estudiar","ejercicio"]}';
const datosReales = JSON.parse(textoJSON);

console.log(datosReales.nombre);  // "Laura"
console.log(datosReales.tareas);  // ["estudiar", "ejercicio"]

forEach(): recorrer arrays sin complicarte

forEach() ejecuta una función para cada elemento de un array. Nada más. Es la forma más legible de recorrer una lista y la que menos errores genera comparada con el bucle for clásico, donde es fácil liar el índice.

JavaScript — forEach vs for tradicional 📋
const frutas = ["manzana", "plátano", "naranja"];

// Forma antigua
for (let i = 0; i < frutas.length; i++) {
  console.log(frutas[i]);
}

// Con forEach — más limpio, sin índices que liar
frutas.forEach(fruta => {
  console.log(fruta);
});

También puedes acceder al índice si lo necesitas, pasándolo como segundo parámetro:

JavaScript 📋
frutas.forEach((fruta, index) => {
  console.log(index, fruta);
});
// 0 manzana
// 1 plátano
// 2 naranja

localStorage: el cajón del navegador

localStorage guarda texto en el navegador del usuario. Los datos persisten aunque cierres la pestaña o el navegador. Solo desaparecen si los borras manualmente o limpias el almacenamiento del navegador.

JavaScript 📋
// Guardar
localStorage.setItem("usuario", "María");

// Recuperar
const usuario = localStorage.getItem("usuario");
console.log(usuario); // "María"

// Eliminar
localStorage.removeItem("usuario");

El problema es que localStorage solo guarda texto. Si intentas guardar un array u objeto directamente, lo convierte a string con [object Object] y pierdes todos los datos. Por eso necesitas JSON.stringify al guardar y JSON.parse al recuperar. Esto es algo que casi todo el mundo descubre a base de romperse la cabeza.

Proyecto: lista de tareas con localStorage

Con estos tres conceptos ya tienes todo lo necesario para hacer algo útil. Una lista de tareas que no desaparece al recargar la página.

Primero el HTML mínimo:

HTML 📋
<div id="app">
  <h2>Mi Lista de Tareas</h2>
  <input type="text" id="nuevaTarea" placeholder="Escribe una tarea...">
  <button id="agregarBtn">Agregar</button>
  <ul id="listaTareas"></ul>
  <button id="limpiarBtn">Limpiar Todo</button>
</div>

Y el JavaScript completo con todo conectado:

JavaScript 📋
let tareas = [];

const inputTarea   = document.getElementById('nuevaTarea');
const botonAgregar = document.getElementById('agregarBtn');
const listaTareas  = document.getElementById('listaTareas');
const botonLimpiar = document.getElementById('limpiarBtn');

// Guardar array en localStorage — stringify convierte a texto
function guardarTareas() {
  localStorage.setItem('misTareas', JSON.stringify(tareas));
}

// Recuperar tareas — parse convierte el texto de vuelta a array
function cargarTareas() {
  const guardadas = localStorage.getItem('misTareas');
  if (guardadas) {
    tareas = JSON.parse(guardadas);
  }
}

// forEach recorre el array y crea un elemento por tarea
function mostrarTareas() {
  listaTareas.replaceChildren();

  tareas.forEach((tarea, index) => {
    const li            = document.createElement('li');
    li.textContent     = tarea;

    const btnEliminar  = document.createElement('button');
    btnEliminar.textContent = '❌';
    btnEliminar.addEventListener('click', () => eliminarTarea(index));

    li.appendChild(btnEliminar);
    listaTareas.appendChild(li);
  });
}

function agregarTarea() {
  const nueva = inputTarea.value.trim();
  if (nueva) {
    tareas.push(nueva);
    inputTarea.value = '';
    guardarTareas();
    mostrarTareas();
  }
}

function eliminarTarea(index) {
  tareas.splice(index, 1);
  guardarTareas();
  mostrarTareas();
}

function limpiarTodo() {
  tareas = [];
  localStorage.removeItem('misTareas');
  mostrarTareas();
}

botonAgregar.addEventListener('click', agregarTarea);
botonLimpiar.addEventListener('click', limpiarTodo);
inputTarea.addEventListener('keypress', (e) => {
  if (e.key === 'Enter') agregarTarea();
});

document.addEventListener('DOMContentLoaded', () => {
  cargarTareas();
  mostrarTareas();
});

Errores que vas a cometer (y cómo evitarlos)

El primero ya lo hemos visto: acceder a propiedades de JSON sin hacer parse. El segundo es casi igual de común: hacer parse de algo que no existe.

JavaScript — error al parsear null 📋
// ❌ Esto rompe si no hay nada guardado aún
const datos = JSON.parse(localStorage.getItem('misDatos'));
// JSON.parse(null) devuelve null, pero si esperas un array peta

// ✅ Comprueba primero que existe
const guardado = localStorage.getItem('misDatos');
const datos    = guardado ? JSON.parse(guardado) : [];

El tercero es intentar guardar un objeto directamente sin stringify. No da error visible, pero cuando lo recuperas tienes "[object Object]" en vez de tus datos.

Una vez que interiorizas estos tres casos, JSON y localStorage dejan de dar sustos.

El siguiente paso natural es conectar esto con una API real en lugar de localStorage. Si tienes Python instalado, aquí tienes cómo montar el servidor que recibiría esos datos.

JavaScript Básico: Variables, bucles y buenas prácticas

Si algo de este tutorial se te ha atragantado, ahí están los fundamentos que lo sostienen.