2012-07-02 12 views
9

Un prototipo se utiliza para declarar propiedades y métodos para una clase de objetos. Una ventaja del uso del prototipo es que conserva memoria porque todas las instancias de una clase apuntan a las propiedades y métodos del prototipo que conserva la memoria y permite que las propiedades sean tratadas como estáticas por todas las instancias de una clase.¿Hay algún beneficio al usar prototipos en lugar de declarar propiedades en el objeto mismo?

El prototipo se utiliza para herencia a través del encadenamiento de prototipos.

Mi pregunta es muy simple. ¿Por qué usar un prototipo cuando puede hacer:

function car() { 
    this.engine = "v8"; 
} 
function mustang() { 
    // nm, no good way to inherit without using prototypes 
} 

¿Es así? Por lo que el propósito principal de prototipos es triple:

  1. memoria conserva
  2. proporcionan propiedades estáticas
  3. es la única manera de que un tipo de referencia a heredar de una superclase
+1

No estoy seguro de lo que estás preguntando ... Parece que dices "simplemente puedes hacer ...", pero luego en el comentario de ese guión dices "no hay una buena manera de [hacerlo]" . ¿No se contradice a sí mismo? – Joeytje50

+1

Creo que se dio cuenta de que sus pensamientos estaban equivocados en parte al hacer la pregunta. En cualquier caso, él no ha estado en stackexchange desde que publicó la pregunta hace 18 meses, por lo que no tiene sentido hablar con él. Fui yo quien todavía se preguntaba ... – Aerovistae

+0

si no usas el prototipo, puedes hacer la función mustang() {car.apply (this); } – Serge

Respuesta

0

prototipos es mucho más que eso. También puede extender clases y instancias de objetos ya existentes con métodos y propiedades durante el tiempo de ejecución.

Esto debería explicarlo de una manera muy comprensible: http://javascript.info/tutorial/inheritance

0

Si se preocupan por las convenciones siguientes para que la gente (y que por la carretera) entienden realmente su código, usted no debe poner this.engine="v8" en el constructor. El prototipo está destinado a definir propiedades para cada automóvil, y el constructor está destinado a definir instancias individuales. Entonces, ¿por qué pondría algo que sea cierto para cada instancia smack dab en el constructor? Esto pertenece al prototipo. Hay algo que decir para poner las cosas en su lugar, incluso si ambas cosas terminan haciendo lo mismo. Su código será comprensible para usted y para otros.

1

con respecto a su tres puntos:

  1. Los prototipos no son necesariamente con más prestaciones, especialmente para cadenas de prototipos que se convierten en largo o contienen muchos miembros. Cuanto menor es el prototipo y más corta es la cadena, más puede el compilador del navegador optimizarlo. En última instancia, es necesario formular esta pregunta para las aplicaciones individuales, sus necesidades individuales y los navegadores que se seleccionan (que pueden variar ampliamente en rendimiento).
  2. Por definición, los miembros estáticos requieren objetos. Es decir, los miembros estáticos pertenecen a un objeto en sí mismo y no a una instancia específica. Los objetos son la única forma de crear propiedades estáticas en JavaScript. Tenga en cuenta que los literales de objeto, que son un tipo de objeto "especial", son esencialmente estáticos.
  3. Se podría implementar su propio tipo de objeto que permitiría algo así como la herencia (es decir, jQuery.extend), pero en lo que respecta a los tipos de referencia, los prototipos son la única forma de crear herencia.
+0

¿No es eso jspref mostrar que el prototipo realiza los demás? Solo Chrome 29 y 30 son más o menos lo mismo. Esto se trata de operaciones por segundo y no muestra el consumo de memoria. En el punto 3; la única forma de que 'someEmployer instanceof Person' sea verdadero es usar el prototipo – HMR

+0

HMR, gracias por captar eso; fue un mal ejemplo de mi parte. Edité la respuesta para explicar el motivo en su lugar. –

+0

Sí, podría haber un impacto negativo en el rendimiento https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain#Performance en un bucle que invoca métodos en la parte superior de la cadena de prototipos que puede notar esta. – HMR

2

memoria conserva

Sí lo hace, al crear cientos de casos de coche y todos ellos tienen sus propias funciones (que tienen sus propios ámbitos de cierre) que va a consumir más memoria.

No se ha encontrado una referencia, pero se ha sugerido que Chrome optimiza las funciones de constructor que usan prototipo mejor que las funciones de constructor con todo en el cuerpo del constructor.

proporcionan propiedades estáticas

estático es más como Date.now(), cada instancia tiene miembros de prototipo, pero puede ser llamado en la instancia.

es la única manera de que un tipo de referencia a heredar de una superclase

Puede heredar con Parent.apply(this,arguments); en Child sino que hace las funciones de padres que se extiende más complicado y no hace childInstance instanceof Parent cierto. Lo que hace ese código es ejecutar el código principal con la instancia secundaria a crear como el objeto invocado (this). La herencia generalmente se realiza en 2 lugares.

  1. En el cuerpo del niño Parent.apply(this,arguments); para volver código de inicialización uso de Padres y hacer que los miembros de instancia de padres a ser miembros instancia secundaria (por ejemplo: This.Name).
  2. Establecimiento de Child.prototype en la copia superficial del Parent.prototype Child.prototype=Object.create(Parent.prototype);Child.prototype.constructor=Child; Esto asegurará que los miembros Parent compartidos estén disponibles en instancias Child (como la función getName).

Estos puntos se explican con más detalle aquí: https://stackoverflow.com/a/16063711/1641941

0

En cuanto a sus puntos:

  1. Definitivamente, hay un aumento de rendimiento, especialmente en relación con las funciones - es mucho mejor declarar funciones en el prototipo .
  2. Creo que quiso decir propiedades "públicas" para que la información se recupere escribiendo some_instance.foo. Las propiedades/métodos "estáticos" son diferentes (ver a continuación).
  3. Correcto. La herencia solo puede suceder realmente del prototipo.

Déjame explicarte algunas cosas para ver si esto ayuda. Crear nuevas "clases" en javascript es un proceso bastante sencillo.

var MyClass = new Function(); 

En este punto, el motor es consciente de su nueva clase y sabe "qué hacer" (en términos de rendimiento) cuando crea nuevas instancias de su "clase".

var my_instance = new MyClass(); 

Si desea modificar el prototipo, puede hacerlo y saber que cada instancia va a recibir información actualizada ya que todos ellos comparten el mismo prototipo.

MyClass.prototype.name = "default name"; 
console.log(my_instance.name); //=> default name 

Ahora el motor sabe que hay una propiedad "nombre", que espera un valor de cadena ... va a destinar esos recursos a todos los nuevos y existentes instancias de la clase ... que es muy útil .Tenga en cuenta que la modificación del prototipo de una "clase" existente como esta es un proceso costoso y no debe realizarse con frecuencia (pero tampoco tema hacerlo).

Realmente no puedo hablar por los prosel rendimiento y los contras de declarar ad-hoc propiedades/métodos en una instancia:

my_instance.foo = function() { /* this is not in the prototype chain */ }; 

Mi conjetura es que esto es bastante simple para el motor y es no es gran cosa a menos que lo haga por decenas de miles de objetos al mismo tiempo.

La principal ventaja de utilizar el prototipo de la OMI es que se puede escribir código para ampliar la funcionalidad de un método y saber que todas las instancias de su "clase" se actualizarán en consecuencia:

var old_foo = MyClass.prototype.foo; 
MyClass.prototype.foo = function() { 
    /* new business logic here */ 

    // now call the original method. 
    old_foo.apply(this, arguments); 
}; 

relación a las propiedades "estáticos" , se declara los de la "clase" (constructor) en sí:

// example static property 
MyClass.num_instances = 0; 

Ahora puede crear init/destruir métodos como éste:

MyClass.prototype.init = function() { 
    this.constructor.num_instances++; 
}; 

MyClass.prototype.destroy = function() { 
    this.constructor.num_instances--; 
}; 

// and call the init method any time you create a new instance 
my_instance.init(); 
console.log(MyClass.num_instances); //=> 1 

var instance_2 = new MyClass(); 
instance_2.init(); 
console.log(MyClass.num_instances); //=> 2 

instance_2.destroy(); 
console.log(MyClass.num_instances); //=> 1 

Espero que ayude.

0

(1) No creo que la conservación de la memoria por sí solo es una razón válida para utilizar .prototype, a menos que usted está recibiendo realmente extremo con duplicación de objetos.

(2) La idea de las propiedades estáticas no es realmente una razón para usar .prototype o bien (en mi humilde opinión), porque no se comporta como una propiedad estática tradicional. Usted (hasta donde yo sé) siempre necesita una instancia de objeto antes de poder acceder a la propiedad "estática", lo que hace que no sea para nada estática.

function Car() {} 
Car.prototype.Engine = "V8"; 
// I can't access Car.Engine... I'll always need an instance. 
alert(new Car().Engine); 
// or 
var car1 = new Car(); 
alert(car1.Engine); //you always need an instance. 
//unless you wanted to do 
alert(Car.prototype.Engine); //this is more like a static property, but has an 
//unintended consequence that every instance of Car also receives a .Engine 
//behavior, so don't do this just to create a "static property." 

Cabe señalar que esta idea "estática" no sólo se aplica a las propiedades pero todos los miembros, que incluye métodos (funciones), desde una perspectiva OO tradicional.

Es mejor pensar en prototipos (de nuevo, en mi humilde opinión) como simples objetos inyectados con comportamientos que se vinculan con los objetos instancia. Todas las instancias de Car() pueden tener sus propios miembros de instancia, pero cada instancia de Car() también se inyectará "automáticamente" con todos los miembros/comportamientos de Car.prototype. No es técnicamente lo mismo, pero me parece conveniente pensar en prototipos de esa manera.

//define Car and Car.GoFast 
function Car() {} 
Car.prototype.GoFast = function() { alert('vroom!'); }; 

var car1 = new Car(); 
var car2 = new Car(); 

car1.GoFast(); 
car2.GoFast(); //both call to same GoFast implementation on Car.prototype 

//change the GoFast implementation 
Car.prototype.GoFast = function() { alert('vvvvvrrrrroooooooooommmmm!!!!!'); }; 

car1.GoFast(); 
car2.GoFast(); //both have been "updated" with the new implementation because 
//both car1 and car2 are pointing to the same (singleton) Car.prototype object! 

Car.prototype se comporta como un objeto singleton cuyos miembros/comportamientos han sido inyectado en instancia objetos de tipo de coches.

(3) Los prototipos no deben confundirse para la herencia. Puede obtener un comportamiento que parece ser herencia, pero no lo es. Los miembros/comportamientos en el prototipo permanecen en el objeto prototipo. No se convierten en miembros/comportamientos de su clase derivada, como la verdadera herencia. Es por eso que lo describo más como el prototipo que se "inyecta" en su instancia.

function Car() {} 
Car.prototype.Engine = "V8"; 
var car1 = new Car(); 
var car2 = new Car(); 

alert(car1.Engine); //alerts "V8" 
//There is no "Engine" variable defined within the instance scope of 'car1'. 
//Javascript searches the scope of car1's Type.prototype object to find 'Engine'. 
//Equivalent to: Object.getPrototypeOf(car1).Engine 

//But if we create 'Engine' within the scope of car1 
car1.Engine = "V6"; //Car.prototype was never accessed or updated 
alert(car1.Engine); //we get "V6" 
alert(car2.Engine); //we still get "V8" 
alert(Object.getPrototypeOf(car1).Engine); //we still get "V8"! 

Así que para responder a la pregunta directamente: ¿Hay alguna ventaja de utilizar prototipo en lugar de declarar las propiedades del objeto en sí?

Sí, cuando se quiere compartir la implementación comportamiento entre los objetos de instancia de un tipo dado.Como una coincidencia, reducirá la huella de su memoria, pero esa no es una razón sola para usar prototipos. Tampoco es "crear propiedades estáticas" (que no son), o por herencia (que no lo es).

Cuestiones relacionadas