2012-03-19 20 views
137

Al crear objetos javascript, puedo poner una declaración de método en la función de constructor o en el prototipo. Por ejemplo, digamos que quiero una clase Dog que tenga una propiedad Name y un método Bark. Puedo poner la declaración del método de la corteza en la función constructora:Declarar el método de objeto javascript en la función de constructor vs. en el prototipo

var Dog = function(name) { 
    this.Name = name; 
    this.Bark = function() { 
     alert(this.Name + " bark"); 
    }; 
} 

o que pudiera poner en como un método en el objeto prototipo:

var Dog = function(name) { 
    this.Name = name; 
} 

Dog.prototype.Bark = function() { 
    alert(this.Name + " bark"); 
}; 

Cuando instancias de objetos de tipo Perro, ambos los enfoques parecen funcionar bien:

var dog = new Dog("Fido"); 
dog.Bark(); //Both approaches show "Fido bark" 

¿Debo preferir uno de estos enfoques sobre el otro? ¿Hay alguna ventaja al usar una sobre la otra? Detrás de escena, ¿estos dos enfoques terminan haciendo exactamente lo mismo? ¿Qué enfoque tiende a favorecer la mayoría de las personas?

Gracias por la ayuda.

+1

... y [¿Uso de 'prototipo' frente a 'esto' en Javascript?] (Http://stackoverflow.com/q/310870/1048572) y otros – Bergi

Respuesta

200

Para el ejemplo que proporcione, debe usar el enfoque de prototipo. En general, depende. La principal ventaja del primer enfoque (métodos de inicialización en el constructor) es que puede aprovechar los cierres haciendo uso de variables locales definidas dentro del constructor en sus métodos. Estas variables no son directamente accesibles fuera de la función constructora, por lo que son efectivamente "privadas", lo que significa que su API es más limpia que si estas variables se definieran en su lugar como propiedades del objeto. Algunas reglas generales:

  • Si sus métodos no usan variables locales definidas en su constructor (su ejemplo no), entonces use el enfoque de prototipo.
  • Si está creando muchos Dog s, utilice el enfoque de prototipo. De esta forma, todas las "instancias" (es decir, objetos creados por el constructor Dog) compartirán un conjunto de funciones, mientras que el modo constructor crea un nuevo conjunto de funciones cada vez que se llama al constructor Dog, utilizando más memoria.
  • Si está creando un pequeño número de Dog sy encuentra que el uso de variables locales, "privadas" en su constructor mejora su código, este puede ser el mejor enfoque.Use su criterio y haga algunos puntos de referencia si el rendimiento o el consumo de memoria son las principales preocupaciones.

Es posible utilizar un enfoque híbrido por el cual solo los métodos que necesitan acceso a las variables de constructor privadas locales se definen en el constructor mientras que otros métodos se asignan al prototipo. Por ejemplo, el siguiente código usa una variable local en el constructor para mantener un registro del número de veces que este perro ha ladrado manteniendo el número real en privado, por lo que los métodos relacionados con los ladridos se definen dentro del constructor. El movimiento de cola no requiere acceso a la cantidad de ladridos, por lo tanto, ese método se puede definir en el prototipo.

var Dog = function(name) { 
 
    this.name = name; 
 

 
    var barkCount = 0; 
 

 
    this.bark = function() { 
 
     barkCount++; 
 
     alert(this.name + " bark"); 
 
    }; 
 

 
    this.getBarkCount = function() { 
 
     alert(this.name + " has barked " + barkCount + " times"); 
 
    }; 
 
}; 
 

 
Dog.prototype.wagTail = function() { 
 
    alert(this.name + " wagging tail"); 
 
}; 
 

 
var dog = new Dog("Dave"); 
 
dog.bark(); 
 
dog.bark(); 
 
dog.getBarkCount(); 
 
dog.wagTail();

+3

¡Buena respuesta, Tim! –

+0

@Tim Down Así que estoy seguro de la respuesta, estás diciendo que usar métodos en el constructor es algo bueno si las variables locales están en la mezcla porque les acelera el tiempo de acceso, ¿correcto? – Sethen

+3

@SethenMaleno: Realmente no estaba considerando la velocidad de acceso a las variables, que es algo que generalmente no debería ser una consideración importante. Mi argumento principal a favor de la creación de métodos en el constructor es que mantiene esas variables privadas en lugar de tener que definir propiedades en el objeto que sería mejor no ser accesible. –

8

La gran mayoría del código javascript que he visto utiliza el método prototipo. Creo que hay tres razones para esto que puedo pensar en la parte superior de mi cabeza. La primera es que evita que cada clase sea un gran constructor necesitas toda la claridad que puedas tener.

El segundo es la eficiencia. Cuando declaras métodos en el constructor, estás creando una nueva instancia del objeto función para cada instancia del objeto, y también vinculando el alcance del constructor a cada una de estas funciones (es decir, pueden hacer referencia, por ejemplo, al argumentos al constructor, que luego nunca pueden ser creados mientras el objeto viva). Cuando declara métodos en el prototipo, hay una sola copia del objeto de función que utilizan todas las instancias: las propiedades del prototipo no se copian en las instancias.

Una tercera razón es que puede "extender" una clase de varias maneras cuando utiliza el método prototipo, como el prototipo de encadenamiento utilizado por Backbone.js y la construcción de clase de CoffeeScript.

11

Los dos son diferentes: El primero almacenará la referencia al método de solamente en el objeto prototipo mientras que la segunda solución almacenará el método en cada del objeto . Esto significa que cada objeto contendrá un puntero adicional y, por lo tanto, ocupará un poco más de memoria cada uno.

El método por objeto permite que el método haga referencia a variables en el constructor (un cierre) y, por lo tanto, le permite acceder a algunos datos a los que no puede acceder desde un prototipo de métodos.

Por último, un método prototipo puede ser cambiado más adelante, es decir puede redefinir Bark en tiempo de ejecución en el objeto prototipo, y este cambio va a funcionar para todos los objetos con este prototipo (ya que el método siempre se busca a través de la prototipo).

Cuestiones relacionadas