tutorial herencia es6 javascript prototypal-inheritance

javascript - es6 - ¿Las mejores prácticas de herencia prototípica?



javascript prototype vs class (5)

Estoy ingresando a JavaScript y estoy tratando de envolver mi cabeza en torno a la herencia prototípica. Parece que hay varias formas de lograr el mismo efecto, por lo que quería ver si existen las mejores prácticas o razones para hacer las cosas de una manera sobre la otra. Esto es lo que estoy hablando:

// Method 1 function Rabbit() { this.name = "Hoppy"; this.hop = function() { console.log("I am hopping!"); } } // Method 2 function Rabbit() {} Rabbit.prototype = { name: "Hoppy", hop: function() { console.log("I am hopping!"); } } // Method 3 function Rabbit() { this.name = "Hoppy"; } Rabbit.prototype.hop = function() { console.log("I am hopping!"); } // Testing code (each method tested with others commented out) var rabbit = new Rabbit(); console.log("rabbit.name = " + rabbit.name); rabbit.hop();

Todos estos parecen tener el mismo efecto individualmente (a menos que me esté perdiendo algo). Entonces, ¿se prefiere un método sobre el otro? ¿Cómo lo haces?


Cuando coloca un método en el prototipo, cada objeto de instancia comparte la misma referencia al método . Si tienes 10 instancias, hay 1 copia del método.

Cuando hace lo que hizo en el ejemplo 1, cada objeto de instancia tiene su propia versión del mismo método, por lo que si crea 10 de sus objetos, hay 10 copias del código en ejecución.

El uso del prototipo funciona porque javascript tiene una maquinaria para la ejecución de una función asociada con una instancia, es decir, establece this propiedad para la ejecución de la función.

Por lo tanto, es preferible utilizar el prototipo ya que usa menos espacio (a menos que, por supuesto, eso es lo que usted quiere).

En el método 2, está configurando el prototipo estableciéndolo igual a un objeto literal. Tenga en cuenta que aquí está configurando una propiedad, lo que creo que no tiene intención de hacer, ya que todas las instancias obtendrán la misma propiedad.

En el Método 3, usted está construyendo el prototipo una asignación a la vez.

Prefiero el método 3 para todas las cosas. Es decir, en mi constructor establezco los valores de mi propiedad.

myObj = function(p1){ this.p1; // every instance will probably have its own value anyway. } myObj.prototype.method1 = function(){..} // all instances share the same method, but when invoked **this** has the right scope.


Este es un tema importante que a menudo se malinterpreta. Depende de lo que estés tratando de hacer. En términos generales, la respuesta de hvgotcode es correcta. Cualquier objeto que se ejemplifique con frecuencia debe adjuntar métodos y propiedades al prototipo.

Pero hay ventajas para los demás en situaciones muy específicas. Lea esto, incluidos los comentarios: http://net.tutsplus.com/tutorials/javascript-ajax/stop-nesting-functions-but-not-all-of-them/

Hay ocasiones en que el método 1 anterior ayuda, lo que le permite tener métodos y propiedades legibles / grabables "privadas". Si bien a menudo esto no vale la pena sacrificarlo en objetos muy instanciados, para objetos creados solo una o varias veces, o sin muchas asignaciones internas, o si se encuentra en un entorno de equipo de desarrolladores con muchos niveles diferentes de habilidades y sensibilidades, puede ser de ayuda

Algunos desarrolladores incorporan otra buena estrategia que intenta salvar algunas de las deficiencias de las otras. Es decir:

var Obj = function() { var private_read_only = ''value''; return { method1: function() {}, method2: function() {} }; };


Hacer algunas pruebas de rendimiento (declarar alrededor de 1 milion de variables de conejo). El primer método será el que más tiempo y memoria consuma.


Veamos los ejemplos uno por uno. Primero:

function Rabbit() { this.name = "Hoppy"; this.hop = function() { //Every instance gets a copy of this method... console.log("I am hopping!"); } } var rabbit = new Rabbit();

El código anterior funcionará, como ha dicho en su pregunta. Creará una nueva instancia de la clase Rabbit . Cada vez que cree una instancia, una copia del método de hop se almacenará en la memoria para esa instancia.

El segundo ejemplo se veía así:

function Rabbit() {} Rabbit.prototype = { name: "Hoppy", hop: function() { //Now every instance shares this method :) console.log("I am hopping!"); } } var rabbit = new Rabbit();

Esta vez, cada instancia de Rabbit compartirá una copia del método de hop . Eso es mucho mejor ya que utiliza menos memoria. Sin embargo, todos los Rabbit tendrán el mismo nombre (suponiendo que no se oculte la propiedad del name en el constructor). Esto se debe a que el método se hereda del prototype . En JavaScript, cuando intenta acceder a una propiedad de un objeto, esa propiedad se buscará primero en el objeto en sí. Si no se encuentra allí, observamos el prototype (y así sucesivamente, subimos la cadena del prototipo hasta que alcanzamos un objeto cuya propiedad prototype es null ).

Tu tercer ejemplo es más o menos como lo haría yo. Los métodos compartidos entre instancias deben ser declarados en el prototype . Las propiedades como el name , que es posible que desee establecer en el constructor, se pueden declarar por instancia:

function Rabbit(rabbitName) { this.name = rabbitName; } Rabbit.prototype.hop = function() { console.log("Hopping!"); }


// option 4 var Rabbit { constructor: function () { this.name = "Hoppy"; return this; }, hop: function() { console.log("I am hopping!"); } }; var rabbit = Object.create(Rabbit).constructor(); console.log("rabbit.name = " + rabbit.name); rabbit.hop();

Cuando se hace OO prototípico, usar funciones new y constructoras es completamente opcional.

Como ya se ha señalado, si puede compartir algo a través del prototipo, hágalo. Los prototipos son más eficientes en cuanto a memoria y son más baratos en términos de tiempo de creación de instancias.

Sin embargo, una alternativa perfectamente válida sería

function Rabbit() { // for some value of extend https://gist.github.com/1441105 var r = extend({}, Rabbit); r.name = "Hoppy"; return r; }

Aquí su extensión "instancias" con las propiedades del "prototipo". La única ventaja que tiene el OO prototípico real es que es un enlace activo, lo que significa que los cambios en el prototipo se reflejan en todas las instancias.