Las funciones constructoras son funciones especiales que se usan para crear múltiples objetos con la misma estructura. Se llaman con la palabra clave new y crean instancias (copias) del objeto.
NotaAnalogía: Una función constructora es como un molde para hacer galletas. El molde define la forma, y cada galleta que haces es una instancia única pero con la misma estructura.
// Función constructora (se escribe con mayúscula por convención)
function Persona(nombre, edad) {
this.nombre = nombre
this.edad = edad
}
// Creamos instancias
const ana = new Persona('Ana', 25)
const carlos = new Persona('Carlos', 30)
console.log(ana.nombre) // "Ana"
console.log(carlos.nombre) // "Carlos"
console.log(ana.edad) // 25
console.log(carlos.edad) // 30
Nota¿Qué es el
this? Es una referencia al objeto que se está creando. En este caso,thisse refiere a la instancia de la persona que se está creando.
new?Cuando usas new con una función constructora, JavaScript hace 4 cosas automáticamente:
function Persona(nombre) {
// 1. Crea un objeto vacío: this = {}
// 2. Establece el prototipo: this.__proto__ = Persona.prototype
this.nombre = nombre
// 3. Ejecuta el código de la función
// 4. Retorna this automáticamente
}
const ana = new Persona('Ana')
Diagrama del proceso:
new Persona('Ana')
↓
1. this = {}
2. this.__proto__ = Persona.prototype
3. this.nombre = 'Ana'
4. return this
↓
Objeto ana
prototypeTodas las funciones constructoras tienen una propiedad especial llamada prototype. Aquí es donde ponemos los métodos que queremos que compartan todas las instancias.
function Coche(marca, modelo) {
this.marca = marca
this.modelo = modelo
}
// Añadimos métodos al prototype
Coche.prototype.acelerar = function () {
console.log(`${this.marca} ${this.modelo} está acelerando`)
}
Coche.prototype.frenar = function () {
console.log(`${this.marca} ${this.modelo} está frenando`)
}
// Creamos instancias
const coche1 = new Coche('Toyota', 'Corolla')
const coche2 = new Coche('Honda', 'Civic')
// Ambos pueden usar los métodos del prototype
coche1.acelerar() // "Toyota Corolla está acelerando"
coche2.frenar() // "Honda Civic está frenando"
¿Qué diferencia hay entre prototype y __proto__? ¡Es muy importante y uno de los errores más comunes en JavaScript!
prototype de la función constructorafunction Animal(nombre) {
this.nombre = nombre
}
Animal.prototype.dormir = function () {
console.log(`${this.nombre} está durmiendo`)
}
const perro = new Animal('Rex')
// prototype vs __proto__
console.log(Animal.prototype) // "object"
console.log(perro.__proto__) // "object"
// Ambos apuntan al mismo prototipo
console.log(Animal.prototype === perro.__proto__) // true
Diagrama visual:
Función Animal Instancia perro
┌─────────────────────┐ ┌─────────────────────┐
│ function Animal() │ │ nombre: "Rex" │
│ │ │ │
│ prototype: { │◀─────┤ __proto__ │
│ dormir() {...} │ │ │
│ constructor: ... │ └─────────────────────┘
│ } │
└─────────────────────┘
Buena práctica: Las propiedades específicas van en la función constructora, los métodos compartidos van en el prototype.
function Persona(nombre, edad) {
// Propiedades específicas de cada instancia
this.nombre = nombre
this.edad = edad
}
// Métodos compartidos en el prototype
Persona.prototype.saludar = function () {
console.log(`Hola, soy ${this.nombre}`)
}
Persona.prototype.cumplirAnios = function () {
this.edad++
console.log(`¡Feliz cumpleaños! Ahora tengo ${this.edad} años`)
}
const ana = new Persona('Ana', 25)
const carlos = new Persona('Carlos', 30)
ana.saludar() // "Hola, soy Ana"
carlos.saludar() // "Hola, soy Carlos"
ana.cumplirAnios() // "¡Feliz cumpleaños! Ahora tengo 26 años"
Sin prototype, cada instancia tendría su propia copia del método:
// ❌ Ineficiente - cada instancia tiene su propia función
function PersonaMala(nombre) {
this.nombre = nombre
this.saludar = function () {
console.log(`Hola, soy ${this.nombre}`)
}
}
// ✅ Eficiente - todas las instancias comparten la misma función
function PersonaBuena(nombre) {
this.nombre = nombre
}
PersonaBuena.prototype.saludar = function () {
console.log(`Hola, soy ${this.nombre}`)
}
Comparación de memoria:
PersonaMala (ineficiente) PersonaBuena (eficiente)
┌─────────────────────────────┐ ┌─────────────────────────────┐
│ ana1: { │ │ ana2: { │
│ nombre: "Ana", │ │ nombre: "Ana", │
│ saludar: function() {...} │ │ __proto__: { │
│ } │ │ saludar: function(){} │
│ │ │ } │
│ carlos1: { │ │ } │
│ nombre: "Carlos", │ │ │
│ saludar: function() {...} │ │ carlos2: { │
│ } │ │ nombre: "Carlos", │
└─────────────────────────────┘ │ __proto__: ───────────────┼──┐
│ } │ │
└─────────────────────────────┘ │
↑_________________________________│
Misma función compartida
JavaScript nos da herramientas para verificar si un objeto es instancia de una constructor function:
function Vehiculo(tipo) {
this.tipo = tipo
}
const coche = new Vehiculo('automóvil')
const moto = new Vehiculo('motocicleta')
// instanceof - verifica si un objeto es instancia de una función
console.log(coche instanceof Vehiculo) // true
console.log(moto instanceof Vehiculo) // true
console.log(coche instanceof Array) // false
// constructor - referencia a la función que creó el objeto
console.log(coche.constructor === Vehiculo) // true
console.log(moto.constructor === Vehiculo) // true
Puedes crear jerarquías de herencia combinando constructor functions:
// Constructor padre
function Animal(nombre) {
this.nombre = nombre
}
Animal.prototype.respirar = function () {
console.log(`${this.nombre} está respirando`)
}
// Constructor hijo
function Perro(nombre, raza) {
Animal.call(this, nombre) // Llama al constructor padre
this.raza = raza
}
// Establecemos la herencia
Perro.prototype = Object.create(Animal.prototype)
Perro.prototype.constructor = Perro
// Añadimos métodos específicos
Perro.prototype.ladrar = function () {
console.log(`${this.nombre} está ladrando: ¡Guau!`)
}
const rex = new Perro('Rex', 'Labrador')
rex.respirar() // "Rex está respirando" (heredado)
rex.ladrar() // "Rex está ladrando: ¡Guau!" (propio)
Cadena de prototipos resultante:
rex → Perro.prototype → Animal.prototype → Object.prototype → null
Inicia sesión
Para guardar tu progreso y desbloquear logros
Funciones constructoras:
new para crear instanciasthis se refiere a la nueva instanciaLa propiedad prototype:
Instancias (objetos):
new__proto__ apunta al prototype de la funciónVentajas de usar funciones constructoras:
instanceofEste sistema de constructor functions fue la base de la programación orientada a objetos en JavaScript antes de que llegaran las clases modernas de ES6.