Volver a JavaScript Intermedio
JavaScript
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()]);