2009-08-23 16 views
8

Aquí hice dos objetos; uno tiene métodos de acceso creados en el constructor, el otro en el prototipo. ¿Por qué elegir uno de estos sobre el otro?Prototipo vs. No, ¿qué son los beneficios?

function spy1(name){ 
    this.name = name; 
    var secret; 
    this.setSecret = function(message){ 
    secret = message; 
    }; 
    this.getSecret = function(){ 
    return secret; 
    }; 
} 

function spy2(name){ 
    this.name = name; 
    this.secret; 
    /* (see comment) was: 
    var secret; 
    */ 
} 
spy2.prototype.setSecret = function(message){ 
    this.secret = message; 
    /*was: 
    secret = message; 
    */ 
}; 
spy2.prototype.getSecret = function(){ 
    return this.secret; 

    /*was: 
    return secret; 
    */ 
}; 

bond = new spy1("007"); 
smart = new spy2("86"); 

bond.setSecret("CONTROL is a joke."); 
smart.setSecret("The British Secret Service is for sissies."); 
+1

Tenga en cuenta que en su prototipo de caso, está (presumiblemente inadvertidamente) creando una variable global implícita 'secret' que no tiene nada que ver con la variable declarada (y no utilizada)' secret' en su función de constructor. Esa variable global (una propiedad del objeto global), al ser global, será compartida por todas las instancias de 'spy2', que supongo que no es lo que estabas tratando de hacer. –

+0

Gracias. Eso fue de hecho inadvertido. Cambié el código; ¿Es esto correcto ahora? Entonces, realmente, un prototipo no puede modificar las variables privadas del objeto. –

Respuesta

8

El differrence primordial es que en el primer ejemplo, y sin prototipo, la implementación y getSecretsetSecret función residirá en cada instancia de Spy1.

En el segundo ejemplo, las funciones se definen en el prototipo, y todos los casos se refieren a ellos directamente, puede probarlo:

var bond = new spy1("007"), 
    bond2 = new spy1("007"); 

bond.getSecret === bond2.getSecret; // <-- false since they are two functions 

var smart = new spy2("86"), 
    smart2 = new spy2("86"); 


smart.getSecret === smart2.getSecret; // <-- true since is the same function 
             // on all instances 

También tenga en cuenta lo que @ T. J. comentado, en su segundo ejemplo, utilizando el prototipo, no tiene acceso al cierre de la función del constructor, y para eso está haciendo una variable global window.secret.

Si tiene la intención de trabajar con privileged methods, extendiendo el prototipo no es una opción, todos los métodos que necesitan acceder a las variables definidas dentro del ámbito de la función constructora necesidad de ser declaradas dentro de ella ...

Vea también: Closures.

+1

... que (en beneficio del que pregunta) tiene graves ramificaciones en el uso de la memoria y, si es posible, debe evitarse. La versión sin prototipo tiene la ventaja de que puede tener vars de instancia verdaderamente privados, porque las funciones miembro son cierres. (Aunque no de la manera en que se hace en la pregunta del interrogador.) –

+0

Puede tener graves ramificaciones en el uso de la memoria, pero si solo está creando un número pequeño de instancias, no tiene de qué preocuparse. –

1

Con la segunda versión terminas con un "constructor" más limpio.

+1

Sí, y también termino con cosas que están relacionadas con el tipo de clase flotando por sí mismas, no visiblemente como parte de la clase. Eso me molesta un poquito. –

5

En su primer ejemplo, está creando nuevas funciones para cada instancia del objeto cuando crea una instancia nueva. En el segundo, solo se crea una copia única de la función que es utilizada por todos instancias.

La segunda manera puede ahorrar memoria. También puede usar prototype chaining para implementar la herencia.

Por cierto, su segundo ejemplo no funcionará como está escrito. la variable secret en spy2 es local para el constructor. En las funciones setSecret y getSecret en el prototipo, está accediendo a una sola variable global.

+0

Ah, ya veo. Entonces, si realmente quiero variables privadas, no puedo usar el prototipo. –

Cuestiones relacionadas