¿Qué significa que Javascript es un lenguaje basado en prototipos?

Respuestas:

291

La herencia de prototipos es una forma de reutilización de código orientado a objetos . Javascript es uno de los únicos lenguajes orientados a objetos [convencionales] que utiliza la herencia prototípica. Casi todos los demás lenguajes orientados a objetos son clásicos.

En herencia clásica , el programador escribe una clase, que define un objeto. Se pueden crear instancias de varios objetos de la misma clase, por lo que tiene código en un lugar que describe varios objetos en su programa. Las clases se pueden organizar en una jerarquía, promoviendo la reutilización del código. El código más general se almacena en una clase de nivel superior, de la que heredan las clases de nivel inferior. Esto significa que un objeto está compartiendo código con otros objetos de la misma clase, así como con sus clases principales.

En la forma de herencia prototípica , los objetos heredan directamente de otros objetos. Todo el negocio sobre las clases desaparece. Si quieres un objeto, solo escribe un objeto. Pero la reutilización del código sigue siendo algo valioso, por lo que los objetos pueden vincularse en una jerarquía. En javascript, cada objeto tiene un enlace secreto al objeto que lo creó, formando una cadena. Cuando se le pide a un objeto una propiedad que no tiene, se le preguntará a su objeto padre ... continuamente en la cadena hasta que se encuentre la propiedad o hasta que se alcance el objeto raíz.

Cada función en JavaScript (que son objetos en sí) en realidad tiene un miembro llamado "prototipo", que es responsable de proporcionar valores cuando se les solicita un objeto. Tener este miembro permite que funcione el mecanismo constructor (mediante el cual los objetos se construyen a partir de funciones). Agregar una propiedad al prototipo de un objeto de función lo hará disponible para el objeto construido, así como para todos los objetos que heredan de él.

Ventajas

Puede que no haya una regla rápida y dura de por qué la herencia de prototipos es una forma ventajosa de reutilización de código. La reutilización del código en sí es ventajosa, y la herencia de prototipos es una forma sensata de hacerlo. Podría argumentar que la herencia de prototipos es un modelo bastante simple de reutilización de código, y que el código puede reutilizarse en gran medida de forma directa . Pero las lenguas clásicas ciertamente también pueden lograr esto.

Nota al margen : @ Andrew Hedges hace un buen punto, que en realidad hay muchos lenguajes prototípicos. Vale la pena señalar que estos otros existen, pero también vale la pena señalar que ninguno de ellos está cerca de la corriente principal. NewtonScript pareció tener algo de tracción por un tiempo, pero murió con su plataforma. También es posible extender algunos lenguajes modernos de manera que agreguen capacidades prototípicas.

keparo
fuente
99
Hola Kelly Si bien JavaScript es, con mucho, el lenguaje prototípico más popular, hay muchos otros: en.wikipedia.org/wiki/Prototype-based_programming#Languages
Andrew Hedges
2
Hola Andrew Buen punto. Debería haber sido más claro. Tomaré nota de ello.
keparo
3
Lea esto también developer.mozilla.org/en/JavaScript/Guide/…
pramodc84
1
+1 para una gran respuesta. Un comentario menor: para mí, la herencia clásica parece más "directa" que prototípica. De hecho, realmente veo el objeto prototipo como un mero enlace (a otros objetos), mientras que en una OOP compilada considero que la clase base es "directamente heredada". Como tal, los objetos prototípicos están encadenados en lugar de heredados (la herencia es algo falsa). ¿Alguna idea?
Prisionero CERO
3
@PrisonerZERO: Yo diría que la herencia prototípica es más directa que clásica. En lugar de que el objeto B apunte a una clase que hereda de la clase a la que apunta el objeto A, apunta directamente al objeto A y dice "soy exactamente como ese objeto, excepto ...". Lo importante de la herencia prototípica, y lo que parece más difícil de internalizar para la mayoría de las personas, es que no distingue las instancias de los tipos. Cada objeto es tanto un tipo como una instancia. Las distinciones entre los dos son artificiales y deliberadas, y generalmente son un síntoma de estar atrapado en una mentalidad orientada a la clase.
cHao
54

Un lenguaje basado en prototipos, no hace la distinción de clases versus objetos: simplemente tiene objetos. Un lenguaje basado en prototipos tiene la noción de un objeto prototípico, un objeto utilizado como plantilla a partir del cual obtener las propiedades iniciales de un nuevo objeto. Cualquier objeto puede especificar sus propias propiedades, ya sea cuando lo cree o en tiempo de ejecución. Además, cualquier objeto puede asociarse como prototipo para otro objeto , permitiendo que el segundo objeto comparta las propiedades del primer objeto.

Guido
fuente
66
Una muy buena explicación, pero un poco engañosa con el comentario sobre la "plantilla para las propiedades iniciales". Si cambia el prototipo DESPUÉS de crear una instancia de un objeto, ese objeto aún recibe esas funciones.
nickf
32

La programación basada en prototipos es un estilo de programación orientada a objetos donde las clases no están presentes y la reutilización del comportamiento (o herencia en lenguajes basados ​​en clases) se realiza mediante la clonación de objetos existentes que sirven como prototipos.

CMS
fuente
¿Aun te sientes de esta manera? Porque si es así, entonces esta es la primera explicación para realmente "hacer clic" sólidamente conmigo.
Chazt3n
11

La ventaja / desventaja es que podemos crear nuevos tipos de objetos en tiempo de ejecución sin necesidad de definir clases (código estático). Como la mayoría de las funciones, depende del desarrollador convertirlo en una ventaja / desventaja.

Lo anterior es posible porque los objetos son esencialmente funciones en el script java (también cierres).

questzen
fuente
Los objetos dinámicos son un beneficio de javascript, pero en realidad no están relacionados con que javascript sea un lenguaje prototípico o funcional. En muchos idiomas clásicos puede crear objetos dinámicos en tiempo de ejecución. Los cierres tampoco están relacionados.
keparo
2
Las clases no son necesariamente un código estático: eche un vistazo a Python, en el que las clases son objetos en sí, y están construidas a partir de metaclases que también son objetos.
Tomasz Zieliński
6

En lugar de declarar una estructura de clase, puede crear objetos del mismo tipo y agregarlos a su definición en cualquier momento que desee utilizando el prototipo del objeto. Es más flexible que la forma normal de hacer las cosas.

Greg
fuente
6

Si solo usa objetos en tiempo de ejecución en lugar de una clase en la compilación para construir nuevos objetos, esto abre la posibilidad de extender un objeto sin conocer ningún detalle al respecto. Por supuesto, puede convertirse en una desventaja bastante rápido dependiendo del uso. No hago suposiciones sobre el idioma aquí, por lo que es aplicable a otros idiomas además de javascript que no son tan dinámicos.

myobject.prototype=unkownobject;
myobject.newproperty=1;

Puede obtener el objeto desde casi cualquier lugar; su propio código, de la red, de la base de datos, de enlaces externos, etc.

Tenga en cuenta que un lenguaje no tiene que implementar un prototipo de herencia como javascript. En javascript, un objeto prototipo se comparte simplemente, al igual que sus propiedades, entre los herederos. La alternativa es copiar todas las propiedades del prototipo al nuevo objeto. Cada enfoque tiene sus puntos fuertes en diferentes situaciones. Me gusta el segundo más, pero no es lo que hace javascript.

artificialidiot
fuente
6

Después de leer todas las respuestas, esta es la conclusión.

1) Herencia en la que los objetos se heredan directamente de otros objetos

2) Que no usa clases

3) También se llama programación basada en instancias o programación orientada a prototipos sin clase

4) La reutilización del comportamiento se realiza clonando objetos existentes que sirven como prototipos

5) El objeto utilizado como plantilla del nuevo objeto obtiene propiedades iniciales

Sunil Garg
fuente