Lección 48: Prototype y Cadena de Prototipos
🧠 Concepto
Section titled “🧠 Concepto”JavaScript es un lenguaje basado en prototipos. Cada objeto tiene una propiedad interna [[Prototype]] que apunta a otro objeto. Cuando accedes a una propiedad, JS la busca en el objeto, y si no la encuentra, sigue por la cadena de prototipos.
La cadena de prototipos
Section titled “La cadena de prototipos”const objeto = { a: 1 };console.log(objeto.toString); // función — viene del prototipo Objectconsole.log(objeto.a); // 1 — propia del objetoCuando llamas a objeto.toString(), JS:
- Busca
toStringen el objeto → no está - Busca en
objeto.__proto__(Object.prototype) → lo encuentra
proto vs Object.getPrototypeOf()
Section titled “proto vs Object.getPrototypeOf()”const persona = { nombre: 'Ana' };
// Forma antigua (no recomendada)console.log(persona.__proto__);
// Forma moderna (recomendada)console.log(Object.getPrototypeOf(persona)); // Object.prototype
// Verificar si una propiedad es del prototipoconsole.log(persona.hasOwnProperty('nombre')); // trueconsole.log(persona.hasOwnProperty('toString')); // false💻 Ejemplo
Section titled “💻 Ejemplo”// Añadir métodos al prototipo de clases nativasString.prototype.capitalizar = function() { return this.charAt(0).toUpperCase() + this.slice(1);};
console.log('hola mundo'.capitalizar()); // "Hola mundo"
Array.prototype.primero = function() { return this[0];};
Array.prototype.ultimo = function() { return this[this.length - 1];};
const nums = [1, 2, 3, 4, 5];console.log(nums.primero()); // 1console.log(nums.ultimo()); // 5
// ¡Pero ten cuidado! Modificar prototipos nativos puede causar conflictos
// Herencia prototípica con Object.create()const animal = { respirar() { return 'Respirando'; }, mover() { return 'Moviéndose'; }};
const perro = Object.create(animal);perro.ladrar = function() { return 'Guau!';};
console.log(perro.ladrar()); // "Guau!" (propio)console.log(perro.respirar()); // "Respirando" (heredado)console.log(perro.mover()); // "Moviéndose" (heredado)console.log(Object.getPrototypeOf(perro) === animal); // true⚠️ Nota
Section titled “⚠️ Nota”Modificar el prototipo de tipos nativos (String, Array, Object) está mal visto en producción, especialmente en proyectos con múltiples librerías. Si todos modifican String.prototype, habrá conflictos.
// ❌ Evita esto en proyectos compartidosObject.prototype.saludar = function() { return 'Hola'; };const obj = {};console.log(obj.saludar()); // "Hola" — pero contamina todos los objetos
// ✅ En su lugar, usa funciones auxiliares o clasesLa cadena termina en null. Object.prototype.__proto__ es null.
Entender el prototipo es clave para dominar JavaScript:
- Las clases (ES6) usan prototipos por debajo
- Los métodos de instancia de una clase viven en el prototipo, no en cada instancia
instanceofrecorre la cadena de prototipos para verificar- El patrón delegación (Object.create) es más flexible que la herencia clásica
// Los métodos de clase están en el prototipoclass Ejemplo { metodo() {}}
const instancia = new Ejemplo();console.log(instancia.hasOwnProperty('metodo')); // falseconsole.log(Ejemplo.prototype.hasOwnProperty('metodo')); // true📝 Ejercicio
Section titled “📝 Ejercicio”Usando Object.create(), crea una cadena de prototipos de 3 niveles:
vehiculocon métodoconducir()coche(hereda de vehiculo) con métodoabrirPuertas()miCoche(hereda de coche) con propiedadmarca
Verifica que miCoche tenga acceso a todos los métodos.
const vehiculo = { conducir() { return 'Conduciendo...'; }};
// Crea coche que herede de vehiculo// Crea miCoche que herede de coche
const miCoche = Object.create(coche);miCoche.marca = 'Toyota';
console.log(miCoche.marca); // "Toyota"console.log(miCoche.abrirPuertas()); // ¿?console.log(miCoche.conducir()); // ¿?