JavaScript
Tutorial JavaScript: Herencia
JavaScript herencia: clases y ejemplos claros. Aprende a implementar herencia en clases de JavaScript con ejemplos claros y detallados.
Aprende JavaScript GRATIS y certifícateEn JavaScript, la herencia es un mecanismo que permite a los objetos heredar propiedades y métodos de otros objetos. La herencia en JavaScript es prototípica, lo que significa que se basa en el uso de prototipos en lugar de clases, como ocurre en otros lenguajes de programación basados en objetos, como Java o C#.
Prototipos y la cadena de prototipos
Para entender la herencia en JavaScript, es importante comprender primero el concepto de prototipo. En JavaScript, todos los objetos tienen una propiedad interna llamada [[Prototype]]
(también accesible mediante __proto__
), que hace referencia a otro objeto llamado "prototipo". Este objeto es esencialmente una plantilla desde la cual el objeto hereda propiedades y métodos.
Cuando se intenta acceder a una propiedad o método en un objeto, JavaScript busca primero en el objeto en sí. Si no encuentra esa propiedad o método, busca en el prototipo del objeto. Si aún no encuentra la propiedad o método, sigue buscando en el prototipo de ese prototipo, y así sucesivamente hasta llegar al final de la cadena de prototipos. Este proceso se conoce como "búsqueda de propiedades en la cadena de prototipos" y es el mecanismo principal que permite la herencia en JavaScript.
Creación de objetos y su relación con Prototipos
Existen diversas formas de crear objetos en JavaScript. A continuación se detallan las dos formas más comunes, que permiten establecer la relación de herencia entre objetos.
Funciones constructoras
Una función constructora es una función especial utilizada para crear objetos. Cuando se invoca a una función constructora con el operador new
, crea un nuevo objeto y automáticamente establece su prototipo como el objeto al que apunta la propiedad prototype
de la función constructora.
function Persona(nombre, edad) {
this.nombre = nombre;
this.edad = edad;
}
Persona.prototype.saludar = function() {
console.log('Hola, mi nombre es ' + this.nombre);
}
const persona1 = new Persona('John', 28);
persona1.saludar(); // Hola, mi nombre es John
En este ejemplo, se crea una función constructora Persona
que recibe dos argumentos nombre
y edad
. Luego, se agrega un método saludar
al prototipo de Persona
. Cuando se crea el objeto persona1
, su prototipo se establece automáticamente como Persona.prototype
, lo que permite que persona1
tenga acceso al método saludar
.
Object.create()
La función Object.create()
permite crear un nuevo objeto con un prototipo específico.
const persona = {
saludar: function() {
console.log('Hola, mi nombre es ' + this.nombre)
}
}
const persona1 = Object.create(persona);
persona1.nombre = 'John';
persona1.saludar(); // Hola, mi nombre es John
En este ejemplo, se crea un objeto persona
que representa un prototipo con un método saludar
. Luego, se crea el objeto persona1
utilizando Object.create()
y pasando el objeto persona
como su prototipo, lo que permite que persona1
tenga acceso al método saludar
.
Herencia en JavaScript: subtipos
Una vez entendido el funcionamiento de los prototipos, la herencia en JavaScript puede implementarse creando un subtipo de un objeto existente. Supóngase que se quire crear un objeto Estudiante
que herede del objeto Persona
creado anteriormente.
function Estudiante(nombre, edad, curso) {
// Invocar al constructor de Persona para inicializar las propiedades 'nombre' y 'edad'
Persona.call(this, nombre, edad);
this.curso = curso;
}
// Establecer el prototipo de Estudiante como Persona.prototype
Estudiante.prototype = Object.create(Persona.prototype);
// Ajustar el constructor a Estudiante
Estudiante.prototype.constructor = Estudiante;
// Agregar un nuevo método a Estudiante.prototype
Estudiante.prototype.estudiar = function() {
console.log(this.nombre + ' está estudiando ' + this.curso);
}
const estudiante1 = new Estudiante('Jane', 22, 'Matemáticas');
estudiante1.saludar(); // Hola, mi nombre es Jane
estudiante1.estudiar(); // Jane está estudiando Matemáticas
En este ejemplo, se crea una nueva función constructora llamada Estudiante
. Dentro del constructor de Estudiante
, se invoca al constructor de Persona
mediante Persona.call(this, nombre, edad)
para inicializar las propiedades nombre
y edad
del objeto estudiante. Luego, se establece el prototipo de Estudiante
como Persona.prototype
utilizando Object.create()
. También es importante actualizar el constructor en Estudiante.prototype
para asegurarse de que apunte correctamente al constructor Estudiante
.
Una vez establecida la relación de herencia, se puede agregar un nuevo método estudiar
al prototipo de Estudiante
. Al crear un objeto estudiante1
, este hereda propiedades y métodos tanto de Estudiante.prototype
como de Persona.prototype
.
Herencia de atributos y métodos
Cuando un objeto hereda de otro objeto o "prototipo" en JavaScript, obtiene acceso a todos los atributos y métodos definidos en el prototipo, así como a los atributos y métodos en los prototipos de niveles superiores en la cadena de prototipos.
Herencia de atributos
Los atributos son propiedades que caracterizan a un objeto. Un objeto puede heredar atributos de su prototipo mediante la relación de herencia establecida entre ellos. Al acceder a un atributo en un objeto que no está presente en él, JavaScript busca ese atributo en el prototipo y, si es necesario, en los niveles superiores de la cadena de prototipos hasta encontrar el atributo o llegar al final de la cadena implicando que el atributo no está definido.
En el caso de las funciones constructoras y las clases de ES6, es común heredar atributos mediante el llamado al constructor del objeto del cual se desea heredar utilizando NombreConstructor.call(this, argumentos)
o super(argumentos)
(en el caso de las clases).
Herencia de métodos
Los métodos son funciones asociadas a un objeto que definen su comportamiento. Al heredar métodos en JavaScript, estos se comparten entre todos los objetos instanciados que heredan del mismo prototipo, lo que ahorra memoria y evita la duplicación del código del método. La herencia de métodos se logra al definir métodos en el prototipo del objeto del cual se desea heredar en lugar de definirlos en el objeto en sí.
Al acceder a un método en un objeto que no está presente en él, JavaScript sigue la misma búsqueda en la cadena de prototipos que aplica para los atributos, hasta encontrar el método o llegar al final de la cadena. Debido a que los métodos heredados comparten contexto y acceden a sus propios atributos mediante this
, es importante que los atributos en aquel objeto estén correctamente inicializados.
Herencia mediante 'extends' y 'super'
Con la introducción de ECMAScript 6 (ES6), JavaScript incorporó el concepto de clases, que en realidad es una envoltura alrededor de la herencia basada en prototipos. Aunque las clases no traen algo nuevo en cuanto a herencia en comparación con los prototipos, estas simplifican la sintaxis para utilizar la herencia y hacen que el código sea más fácil de leer y mantener.
Las palabras clave extends
y super
son valiosas en el uso de herencia en clases de JavaScript.
extends
La palabra clave extends
en JavaScript permite establecer que una clase es un subtipo de otra clase, heredando sus atributos y métodos. Al utilizar extends
, JavaScript se encarga automáticamente de establecer el prototipo y el constructor apropiado.
class Persona {
constructor(nombre, edad) {
this.nombre = nombre;
this.edad = edad;
}
saludar() {
console.log('Hola, mi nombre es ' + this.nombre);
}
}
class Estudiante extends Persona {
constructor(nombre, edad, curso) {
super(nombre, edad); // Llamada al constructor de Persona
this.curso = curso;
}
estudiar() {
console.log(this.nombre + ' está estudiando ' + this.curso);
}
}
const estudiante1 = new Estudiante('Jane', 22, 'Matemáticas');
estudiante1.saludar(); // Hola, mi nombre es Jane
estudiante1.estudiar(); // Jane está estudiando Matemáticas
En este ejemplo, al utilizar class
, se define una clase Persona
y una clase Estudiante
. La palabra clave extends
en la definición de Estudiante
indica que esta clase hereda de Persona
.
super
La palabra clave super
en JavaScript se utiliza para acceder o invocar alguno de los métodos o atributos del prototipo o de la clase padre. Por ejemplo, super
se usa para llamar al constructor de la clase padre. En el ejemplo anterior, dentro del constructor de la clase Estudiante
, se llama al constructor de Persona
utilizando super(nombre, edad)
.
super
también se puede utilizar para llamar a métodos de la clase padre dentro de un método de la clase derivada:
class Persona {
// ...
presentar() {
return 'Mi nombre es ' + this.nombre + ' y tengo ' + this.edad + ' años.';
}
}
class Estudiante extends Persona {
// ...
presentar() {
const presentacion = super.presentar();
return presentacion + ' Estoy estudiando ' + this.curso + '.';
}
}
const estudiante1 = new Estudiante('Jane', 22, 'Matemáticas');
console.log(estudiante1.presentar()); // Mi nombre es Jane y tengo 22 años. Estoy estudiando Matemáticas.
En este ejemplo, se redefine el método presentar
en la clase Estudiante
y se utiliza super.presentar()
para invocar el método presentar
de la clase Persona
y obtener la cadena de presentación básica y, luego, agregar información adicional relacionada con el curso.
En resumen, la herencia en JavaScript se basa en prototipos y la cadena de prototipos, y puede simplificarse mediante las palabras clave extends
y super
. Los objetos heredan propiedades y métodos de sus prototipos, lo que permite compartir comportamientos y estructuras entre diferentes objetos. Aunque la herencia en JavaScript es diferente a la herencia basada en clases de otros lenguajes, sigue siendo un enfoque poderoso y flexible para la reutilización de código y la organización de aplicaciones.
Ejercicios de esta lección Herencia
Evalúa tus conocimientos de esta lección Herencia con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Funciones flecha
Polimorfismo
Array
Transformación con map()
Introducción a JavaScript
Gestor de tareas con JavaScript
Manipulación DOM
Funciones
Funciones flecha
Async / Await
Creación y uso de variables
Excepciones
Promises
Funciones cierre (closure)
Herencia
Herencia
Estructuras de control
Selección de elementos DOM
Modificación de elementos DOM
Filtrado con filter() y find()
Funciones cierre (closure)
Funciones
Mapas con Map
Reducción con reduce()
Callbacks
Manipulación DOM
Promises
Async / Await
Eventos del DOM
Async / Await
Promises
Filtrado con filter() y find()
Callbacks
Creación de clases y objetos Restaurante
Reducción con reduce()
Filtrado con filter() y find()
Reducción con reduce()
Conjuntos con Set
Herencia de clases
Eventos del DOM
Clases y objetos
Modificación de elementos DOM
Mapas con Map
Funciones
Tipos de datos
Clases y objetos
Array
Conjuntos con Set
Array
Encapsulación
Clases y objetos
Uso de operadores
Uso de operadores
Estructuras de control
Excepciones
Transformación con map()
Funciones flecha
Selección de elementos DOM
Encapsulación
Mapas con Map
Creación y uso de variables
Polimorfismo
Tipos de datos
Estructuras de control
Todas las lecciones de JavaScript
Accede a todas las lecciones de JavaScript y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A Javascript
Sintaxis
Tipos De Datos
Sintaxis
Variables
Sintaxis
Operadores
Sintaxis
Estructuras De Control
Sintaxis
Funciones
Sintaxis
Funciones Cierre (Closure)
Sintaxis
Funciones Flecha
Programación Funcional
Filtrado Con Filter() Y Find()
Programación Funcional
Transformación Con Map()
Programación Funcional
Reducción Con Reduce()
Programación Funcional
Clases Y Objetos
Programación Orientada A Objetos
Excepciones
Programación Orientada A Objetos
Encapsulación
Programación Orientada A Objetos
Herencia
Programación Orientada A Objetos
Polimorfismo
Programación Orientada A Objetos
Array
Estructuras De Datos
Conjuntos Con Set
Estructuras De Datos
Mapas Con Map
Estructuras De Datos
Manipulación Dom
Dom
Selección De Elementos Dom
Dom
Modificación De Elementos Dom
Dom
Eventos Del Dom
Dom
Callbacks
Programación Asíncrona
Promises
Programación Asíncrona
Async / Await
Programación Asíncrona
Certificados de superación de JavaScript
Supera todos los ejercicios de programación del curso de JavaScript y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender el concepto de herencia en JavaScript y cómo se basa en prototipos.
- Conocer el uso de la propiedad
[[Prototype]]
o__proto__
para establecer la cadena de prototipos. - Aprender cómo crear objetos y funciones constructoras para establecer relaciones de herencia.
- Entender cómo la herencia de atributos y métodos funciona a través de la cadena de prototipos.
- Aprender a utilizar la función
Object.create()
para crear objetos con un prototipo específico. - Conocer el uso de las palabras clave
extends
ysuper
en las clases de ES6 para simplificar la herencia. - Entender cómo agregar o sobrescribir métodos en la cadena de prototipos para personalizar el comportamiento de objetos heredados.
- Saber cómo la herencia permite reutilizar código y compartir comportamientos y estructuras entre objetos en JavaScript.