Volver a JavaScript Intermedio

Prototipos y el Event Loop

Cadena de Prototipos

Cada objeto JavaScript tiene un enlace interno a otro objeto — su prototipo. Las búsquedas de propiedades recorren esta cadena hasta llegar a null.

const animal = { respirar() { console.log('Respirando...'); } }; const perro = Object.create(animal); perro.ladrar = function () { console.log('¡Guau!'); }; perro.ladrar(); // ✅ método propio perro.respirar(); // ✅ encontrado en el prototipo console.log(Object.getPrototypeOf(perro) === animal); // true

Clases como Azúcar Sintáctica

Las clases son azúcar sintáctica — internamente siguen usando la cadena de prototipos.

class Vehiculo { constructor(marca, velocidad) { this.marca = marca; this.velocidad = velocidad; } describir() { return `${this.marca} a ${this.velocidad} km/h`; } } class Auto extends Vehiculo { constructor(marca, velocidad, puertas) { super(marca, velocidad); // Llamar al constructor padre this.puertas = puertas; } describir() { return `${super.describir()} con ${this.puertas} puertas`; } } const auto = new Auto('Toyota', 120, 4); auto.describir(); // "Toyota a 120 km/h con 4 puertas"

El Event Loop

JavaScript es single-threaded pero gestiona el trabajo asíncrono mediante el event loop.

┌─────────────────────────────────┐
│          Call Stack             │  ← Ejecuta código síncrono
└────────────────┬────────────────┘
                 │
┌────────────────▼────────────────┐
│            Web APIs             │  ← setTimeout, fetch, eventos DOM
└────────────────┬────────────────┘
                 │
┌────────────────▼────────────────┐
│         Cola de Callbacks       │  ← callbacks de setTimeout
│         Cola de Microtareas     │  ← Promise .then(), queueMicrotask()
└─────────────────────────────────┘

Prioridad: Las microtareas (Promesas) siempre se ejecutan antes que las macrotareas (setTimeout).

console.log('1 - síncrono'); setTimeout(() => console.log('4 - setTimeout'), 0); Promise.resolve().then(() => console.log('3 - microtarea')); console.log('2 - síncrono'); // Salida: 1, 2, 3, 4

Patrones Async

// Callback hell (evitar) getData(id, (err, data) => { procesarData(data, (err, resultado) => { guardar(resultado, (err, guardado) => { console.log('Listo'); // Anidado profundamente }); }); }); // Cadena de Promesas (mejor) getData(id) .then(data => procesarData(data)) .then(resultado => guardar(resultado)) .then(() => console.log('Listo')) .catch(err => console.error(err)); // Async/await (lo mejor — lee como código síncrono) async function ejecutar(id) { try { const data = await getData(id); const resultado = await procesarData(data); await guardar(resultado); console.log('Listo'); } catch (err) { console.error(err); } }

Combinadores de Promesas

// Todas tienen éxito o todas fallan const [usuarios, posts] = await Promise.all([obtenerUsuarios(), obtenerPosts()]); // La primera en resolver gana const másFrápida = await Promise.race([mirror1(), mirror2(), mirror3()]); // Esperar todas, obtener resultados+errores individualmente const resultados = await Promise.allSettled([a(), b(), c()]); resultados.forEach(r => { if (r.status === 'fulfilled') console.log(r.value); else console.error(r.reason); }); // Primera en tener éxito (ignora rechazos a menos que todas fallen) const primerÉxito = await Promise.any([a(), b(), c()]);