Command Palette

Search for a command to run...

prototype vs __proto__: Diferencias Clave

Entiende la diferencia fundamental entre la propiedad prototype y __proto__, y cuándo usar cada una en JavaScript moderno.

Lectura: 12 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • __proto__ es propiedad de instancias, prototype es propiedad de funciones
  • __proto__ apunta al prototipo del objeto, prototype define el prototipo de instancias
  • Object.getPrototypeOf() es la forma moderna de acceder al prototipo
  • Object.setPrototypeOf() es la forma moderna de cambiar prototipos (evitar)
  • __proto__ está deprecated, usa Object.getPrototypeOf() en su lugar
  • prototype se usa en constructores para definir métodos compartidos

Introducción a prototype vs __proto__

Dos de las propiedades más confusas en JavaScript son __proto__ y prototype. Aunque están relacionadas, tienen propósitos y usos completamente diferentes. Entender la diferencia entre ambas es fundamental para escribir código JavaScript correcto y moderno.

Por qué es importante

La confusión entre estas propiedades puede llevar a errores sutiles en tu código. Conocer la diferencia te ayuda a evitar antipatrones y escribir código más mantenible.

¿Qué es __proto__?

__proto__ es una propiedad que tienen TODOS los objetos en JavaScript (instancias). Esta propiedad apunta al prototipo del objeto, es decir, al objeto del cual hereda propiedades y métodos. Es como un enlace interno que conecta el objeto con su "padre" en la cadena de prototipos.

que-es-proto.js
Loading code...

En este ejemplo, creamos dos objetos: persona y animal. Cada uno tiene su propia propiedad __proto__ que apunta a Object.prototype. Cuando accedemos a persona.__proto__, obtenemos Object.prototype, que es el prototipo compartido de todos los objetos literales.

__proto__ está deprecated

Aunque __proto__ funciona, está oficialmente deprecated. En código moderno, usa Object.getPrototypeOf(obj) para obtener el prototipo de un objeto.

¿Qué es prototype?

prototype es una propiedad especial que tienen SOLO las FUNCIONES (especialmente las funciones constructoras). Esta propiedad define el prototipo que será asignado a todas las instancias creadas con esa función usando el operador new.

que-es-prototype.js
Loading code...

En este ejemplo, creamos una función constructora Persona y agregamos métodos a Persona.prototype. Cuando creamos instancias con new Persona(), cada instancia tiene su __proto__ apuntando a Persona.prototype, permitiéndoles acceder a los métodos compartidos. Las instancias NO tienen la propiedad prototype, solo funciones la tienen.

Eficiencia de memoria

Agregar métodos a prototype en lugar del constructor es más eficiente. Todas las instancias comparten los mismos métodos en memoria en lugar de tener copias duplicadas.

Diferencias Clave

Las diferencias entre __proto__ y prototype son fundamentales para entender cómo funciona la herencia en JavaScript. Aunque ambas se relacionan con prototipos, operan en contextos completamente diferentes.

  • <strong>__proto__</strong>: Existe en TODAS las instancias (objetos), apunta a su prototipo
  • <strong>prototype</strong>: Existe SOLO en FUNCIONES, define el prototipo de instancias futuras
  • <strong>__proto__</strong>: Se establece automáticamente al crear un objeto con new
  • <strong>prototype</strong>: Se configura manualmente agregando propiedades/métodos
  • <strong>Relación</strong>: instancia.__proto__ === Constructor.prototype (siempre true)
  • <strong>Uso</strong>: __proto__ para inspección (deprecated), prototype para definir métodos
diferencias-clave.js
Loading code...

Este ejemplo muestra las diferencias clave entre __proto__ y prototype. La propiedad __proto__ de la instancia apunta al prototipo, mientras que Persona.prototype define las propiedades que heredan las instancias.

Para entender mejor las diferencias, considera esta comparación directa: __proto__ es como un puntero que tiene cada objeto hacia su "plantilla", mientras que prototype es la "plantilla" misma que las funciones usan para crear objetos. Cuando haces new Persona(), JavaScript automáticamente conecta instancia.__proto__ con Persona.prototype.

Regla simple

Si estás trabajando con una función constructora, usa prototype. Si estás inspeccionando un objeto ya creado, usa Object.getPrototypeOf() (no __proto__).

APIs Modernas

JavaScript moderno proporciona APIs estandarizadas y más seguras para trabajar con prototipos. Estas APIs reemplazan el uso de __proto__, que está deprecated y no debería usarse en código nuevo.

apis-modernas.js
Loading code...

Este ejemplo muestra las APIs modernas para trabajar con prototipos. Object.getPrototypeOf() obtiene el prototipo de un objeto de forma estandarizada. Object.setPrototypeOf() permite cambiar el prototipo, pero tiene implicaciones de rendimiento y debe evitarse. Object.create() es la forma preferida de crear objetos con prototipos específicos.

Object.getPrototypeOf() vs __proto__

Object.getPrototypeOf(obj) es la forma moderna y recomendada de obtener el prototipo de un objeto. Es más explícita, está estandarizada, y funciona consistentemente en todos los entornos. Reemplaza completamente el uso de obj.__proto__.

Object.create() para crear objetos

Object.create(proto) es la forma más eficiente y clara de crear objetos con un prototipo específico. Es mejor que usar Object.setPrototypeOf() porque establece el prototipo en el momento de la creación, lo cual es más rápido y menos propenso a errores.

Object.setPrototypeOf() es lento

Cambiar el prototipo de un objeto existente con Object.setPrototypeOf() tiene un impacto negativo significativo en el rendimiento. Los motores JavaScript no pueden optimizar objetos que cambian de prototipo. Usa Object.create() en su lugar.

¿Cuándo Usar Cada Uno?

Saber cuándo usar cada API es crucial para escribir código JavaScript eficiente y mantenible. La regla general es: usa prototype para definir métodos en constructores, y usa Object.getPrototypeOf() (nunca __proto__) cuando necesites inspeccionar prototipos.

  • <strong>Usa prototype</strong>: Para definir métodos compartidos en funciones constructoras
  • <strong>Usa Object.getPrototypeOf()</strong>: Para inspeccionar el prototipo de un objeto
  • <strong>Usa Object.create()</strong>: Para crear objetos con un prototipo específico
  • <strong>Usa class</strong>: Sintaxis moderna preferida para herencia (usa prototype internamente)
  • <strong>NUNCA uses __proto__</strong>: Está deprecated, usa las APIs modernas en su lugar
  • <strong>EVITA Object.setPrototypeOf()</strong>: Es lento, crea el objeto con el prototipo correcto desde el inicio
cuando-usar-cada-uno.js
Loading code...

Este ejemplo muestra cuándo usar cada propiedad. Usamos prototype para agregar un método compartido a todas las instancias de Persona. Usamos __proto__ para inspeccionar la cadena de prototipos. Usamos Object.create() para crear un objeto con un prototipo diferente.

JavaScript moderno: prefiere class

En código moderno, la sintaxis de class es preferida sobre funciones constructoras. Las clases son más legibles y previenen errores comunes, aunque internamente usan prototype.

Resumen: prototype vs __proto__

Conceptos principales:

  • __proto__ existe en instancias, prototype existe en funciones
  • instancia.__proto__ === Constructor.prototype (relación clave)
  • Object.getPrototypeOf() es la API moderna para acceder a prototipos
  • Object.create() crea objetos con prototipo específico
  • Object.setPrototypeOf() es lento, evitar en producción
  • __proto__ está deprecated, usar APIs modernas

Mejores prácticas:

  • Usa prototype para definir métodos en constructores
  • Usa Object.getPrototypeOf() en lugar de __proto__
  • Usa Object.create() para objetos con prototipos específicos
  • Prefiere class en lugar de funciones constructoras
  • NUNCA uses __proto__ en código nuevo
  • Evita Object.setPrototypeOf() por razones de rendimiento