W3docs

Herencia de Clases en JavaScript

Aprende la herencia de clases en JavaScript con extends y super: la cadena de prototipos, sobrescritura de métodos, llamadas al padre y clases nativas.

Introducción a la Herencia de Clases en JavaScript

La herencia de clases es un concepto fundamental de la programación orientada a objetos que permite que una clase herede propiedades y métodos de otra clase. En JavaScript, la herencia de clases se implementa mediante la palabra clave extends, que proporciona una forma de crear una clase derivada que hereda de una clase base.

Para más información sobre la sintaxis básica, consulta JavaScript: Clases y Sintaxis Básica.

Este capítulo explica cómo crear clases derivadas, sobrescribir métodos y propiedades, llamar al padre con super, extender clases nativas como Array y heredar métodos estáticos — además de la cadena de prototipos que hace que todo funcione internamente.

Cómo Funciona la Herencia: La Cadena de Prototipos

La palabra clave class es azúcar sintáctico sobre la herencia prototípica de JavaScript. Cuando escribes class Circle extends Shape, el motor establece dos enlaces:

  • Circle.prototype.__proto__ === Shape.prototype — para que los métodos de instancia se resuelvan subiendo por la cadena.
  • Circle.__proto__ === Shape — para que los métodos estáticos también se hereden.

Cuando lees una propiedad o llamas a un método sobre un objeto, el motor busca primero en el propio objeto. Si no lo encuentra allí, recorre la cadena de prototipos — a Circle.prototype, luego a Shape.prototype, luego a Object.prototype, y finalmente a null — deteniéndose en la primera coincidencia. Esto explica exactamente por qué una instancia de Circle puede llamar a un método definido en Shape.

javascript— editable

Object.getPrototypeOf(obj) devuelve el siguiente eslabón de la cadena (la forma estándar y preferida de inspeccionarla). El acceso heredado obj.__proto__ apunta al mismo objeto. Entender esta cadena explica todo lo que viene a continuación: la sobrescritura funciona porque un prototipo más cercano oculta uno más lejano, y super funciona porque salta explícitamente al prototipo del padre.

Crear una Clase Derivada

Para crear una clase que herede de otra, usamos la palabra clave extends:

javascript— editable

En este ejemplo, Circle extiende Shape, lo que significa que hereda las propiedades y métodos de Shape, y al mismo tiempo proporciona métodos propios. Observa que Circle no define su propio constructor. En JavaScript, las clases derivadas sin un constructor explícito llaman automáticamente a super() con los mismos argumentos que se pasan al constructor de la clase derivada.

Sobrescribir Métodos

Las clases derivadas pueden sobrescribir métodos de sus clases base para proporcionar comportamiento específico a la subclase.

javascript— editable

Aquí, Circle sobrescribe el método print para reflejar su tipo específico.

Llamar a Métodos del Padre con super

También puedes llamar al método de una clase padre desde la clase derivada usando super.methodName(). Esto es útil cuando quieres extender el comportamiento del padre en lugar de reemplazarlo completamente.

javascript— editable

Aquí, super.print() ejecuta la lógica del padre antes de agregar la salida específica de la subclase.

Una Sobrescritura Realista: Calcular el Área

La sobrescritura brilla cuando cada subclase necesita un comportamiento genuinamente diferente. Aquí, una clase base Shape define la interfaz compartida, y cada subclase sobrescribe area() con su propio cálculo real. Llamar a area() sobre un Circle resuelve a Circle.prototype.area, que oculta la versión base.

javascript— editable

Observa que describe() solo está definido en Shape, pero llama a this.area() y obtiene la implementación de la subclase. Eso es la cadena de prototipos en acción: this siempre hace referencia a la instancia real, por lo que la búsqueda de métodos comienza desde Circle o Rectangle.

Sobrescribir Propiedades y Leer super.prop

super no se limita a los métodos — puedes leer una propiedad definida en el prototipo padre con super.prop, lo cual es útil cuando una subclase quiere construir sobre el getter del padre en lugar de reemplazarlo.

javascript— editable

Acceder al Constructor del Padre: la Palabra Clave super

Cuando una clase extiende otra, la función constructora de la clase derivada necesita llamar al constructor del padre usando super() antes de poder usar this. Así es como se usa super en los constructores para garantizar que la clase padre sea inicializada:

javascript— editable

Por Qué super() Debe Ejecutarse Antes que this

En una clase derivada, el objeto instancia no se crea hasta que super() se ejecuta — esa es la tarea del constructor padre. Hasta entonces, this se encuentra en un estado no inicializado, por lo que tocarlo (leer, asignar o incluso devolver el objeto implícitamente) lanza un ReferenceError. Esta es una regla del lenguaje, no una preferencia de estilo.

javascript— editable

Una regla relacionada: si una clase derivada define un constructor, debe llamar a super() en algún punto antes de terminar, o se lanzará el mismo ReferenceError. (Una clase derivada sin constructor explícito está bien — JavaScript inserta constructor(...args) { super(...args); } por ti.) Una vez que super() retorna, this está completamente inicializado y listo para usarse.

Heredar Métodos Estáticos

Los miembros estáticos pertenecen a la clase en sí, no a las instancias. Dado que extends también enlaza Circle.__proto__ con Shape, las clases derivadas heredan los métodos estáticos y pueden llamarlos directamente. Para más información sobre cómo declararlos, consulta Propiedades y Métodos Estáticos de JavaScript.

javascript— editable

Dentro de un método estático, this hace referencia a la clase sobre la que fue invocado, por lo que Shape.create llamado como Circle.create construye un Circle.

Herencia Multinivel

Las cadenas pueden tener más de dos niveles de profundidad. La búsqueda de métodos simplemente sube más por la cadena de prototipos, y super siempre hace referencia al prototipo un nivel por encima de la clase donde se define el método.

javascript— editable

Extender Clases Nativas

Puedes extender clases nativas como Array, Error o Map para crear versiones especializadas que conserven todo el comportamiento nativo mientras añaden el tuyo propio.

javascript— editable

El problema con Symbol.species. Los métodos como map, filter y slice devuelven una nueva colección. Por defecto, devuelven una instancia de tu subclase (MyArray), no un Array simple — lo cual suele estar bien, pero puede sorprender al código que espera un Array real. Puedes volver a arrays simples sobrescribiendo el getter estático Symbol.species.

javascript— editable

Para combinar comportamiento de múltiples fuentes (JavaScript no tiene herencia múltiple), consulta JavaScript Mixins.

Resumen

Puntos clave:

  • Usa extends para derivar una clase; enlaza tanto la cadena de prototipos (métodos de instancia) como la clase en sí (métodos estáticos) con el padre.
  • La búsqueda de métodos y propiedades recorre la cadena de prototipos, deteniéndose en la primera coincidencia — por eso una definición más cercana sobrescribe una más lejana. Inspecciona la cadena con Object.getPrototypeOf().
  • En un constructor derivado, llama a super() antes de this. Hasta que super() se ejecute, la instancia no está inicializada y cualquier uso de this lanza un ReferenceError.
  • Accede al comportamiento del padre explícitamente con super.method() o super.prop, incluso cuando lo hayas sobrescrito.
  • Puedes extender clases nativas como Array — solo ten en cuenta el comportamiento de Symbol.species cuando los métodos devuelvan nuevas colecciones.

Próximos pasos:

Práctica

Práctica
En la herencia de clases de JavaScript, ¿cuáles afirmaciones son verdaderas?
En la herencia de clases de JavaScript, ¿cuáles afirmaciones son verdaderas?
Was this page helpful?