2009-01-12 7 views
11

Este es un seguimiento de una pregunta que acabo de publicar. Me pregunto cómo manejarán todas las variables miembro en clases de JavaScript cuando usen MyClass.prototype para definir métodos.¿Cuál es el mejor enfoque para las variables miembro en javascript orientado a objetos?

Si define todos los métodos en la función constructora:

function MyClass(){ 
this.myMethod = function(){} 
} 

Se puede declarar muy bien las variables miembro y acceder a ellos desde el interior de sus métodos:

function MyClass(){ 
var myVar = "hello"; 
this.myMethod = function(){ 
    alert(myVar); 
} 
} 

Cuando se utiliza el objeto. técnica de prototipo, pierdes esta elegancia y tienes que hacerlo así;

function MyClass(){} 
MyClass.prototype.myVar = "hello"; 
MyClass.prototype.myMethod = function(){alert(this.hello)}; 

no estoy loca por tener que escribir "este" cada vez que accedo a una variable miembro. Quiero utilizar el enfoque Object.prototype por motivos de memoria y flexibilidad, pero parece mucho más complejo en cuanto a la sintaxis. ¿Es así como tu gente generalmente trabaja?

gracias,

-Morgan

+0

En relación con la variabl privada e miembros, puede que le interese usar el compilador de cierre de Google. Cada clase se puede definir en un archivo separado y el compilador aplicará las variables privadas. https://developers.google.com/closure/compiler/docs/js-for-compiler#tag-private –

Respuesta

14

Usted debe obtener más de su aversión a usar el puntero this acceder a variables miembro.

Asignar variables miembro en el constructor, y se puede acceder a ellos con métodos de prototipo:

function Cat(){ 
    this.legs = 4; 
    this.temperament = 'Apathetic'; 
    this.sound = 'Meow'; 
} 

Cat.prototype.speak = function(){alert(this.sound)} 

var cat = new Cat(); 
cat.speak(); 

Si los atributos de los objetos son públicos, pero, como diría Guido, somos todos los adultos aquí. Después de todo, Javascript es un lenguaje de texto sin formato, interpretado libremente. Los beneficios de las variables "privadas" en este entorno son, en el mejor de los casos, inestables.

Digo que sea explícito y obvio acerca de cómo se debe acceder a su objeto, y los infractores se desviarán de eso bajo su propio riesgo.

+0

El problema es, por supuesto, que no puedes tener métodos/vars privados. ¿Podría publicar una forma en la que pueda permitir eso utilizando el método prototipo? – nlaq

+0

ok, ok. Supongo que lo haré. Voy a extrañar mis vars aunque :( – morgancodes

+1

@Nelson - los métodos prototipo nunca tendrán acceso a "variables privadas" (realmente, variables locales para el constructor). Vea mi respuesta aquí: http://stackoverflow.com/questions/436120/javascript-accessing-private-member-variables-from-prototype-defined-functions # 436147 – Triptych

3

Debe utilizar el prototipo para almacenar métodos, porque cuando usted se encuentra con 100 métodos, no son copiados alrededor de entre instancias y no utilizan el mismo prototipo. utilizo algo como lo siguiente:

var myClass = function(){}; 
myClass.prototype = { 
    method1: function(){} 
    ,method2: function(){} 
}; 
+0

Gracias sktrdie, esa es una de las razones principales por las que paso a usar prototipos. Sin embargo, me pregunto cuál es la mejor forma de administrar las variables miembro. ¿Solo necesito resignarme a escribir "esto" mucho más? – morgancodes

+0

re: "this": sí, es una de esas cosas a las que solo tienes que acostumbrarte. –

-2

Usted encontrará una gran cantidad de personas que utilizan el

function name() 
{ 
    var m_var = null; 
    var privateMethod = function() { } 
    this.PublicMethod = function() { } 
} 

incluido yo mismo. Tiendo a no escribir grandes clases de JS y esta sintaxis es bastante fácil de escribir y también permite métodos/variables privados.

EDITAR

Por lo que su me dice que el uso de XML para los paquetes de SOAP sólo para hacer la depuración de un paso más fácil es bien (a pesar de que los desechos XML un montón de espacio y ancho de banda y el tiempo de análisis), pero la adición de una pocos bytes por instancia de objeto javascript no está bien, incluso si nos permite utilizar algunos de los conceptos básicos de OO que deberían existir en el lenguaje desde el principio?

Hmm ...

(por mi comentario XML para leer los comentarios: REST URIs and operations on an object that can be commented on, tagged, rated, etc)

+0

-1. Él quiere usar funciones prototipo para los beneficios de la memoria, que ocasionalmente pueden ser sustanciales. – Triptych

+0

Gracias Nelson, Eso es lo que siempre he hecho, pero recientemente descubrí que this.PublicMethod se copiará una vez para cada instancia. No es un problema si solo tiene un par de instancias, pero si tiene mucho, puede volverse significativo. – morgancodes

+0

Una razón más por la que quería usar el método .prototype era para poder anular o ampliar un método de manera opcional. Usando su enfoque, tengo que esperar hasta después de la instanciación para hacer el cambio. Más lindo si no tengo que preocuparme por eso. – morgancodes

14

El visiblity de de atributos de objeto varía en función de cómo se declaran

function Cat(name) { 

    //private variable unique to each instance of Cat 
    var privateName = 'Cat_'+Math.floor(Math.random() * 100); 

    //public variable unique to each instance of Cat 
    this.givenName = name; 

    //this method has access to private variables 
    this.sayPrivateName = function() { 
     alert(privateName); 
    } 
} 

//this variable is shared by all cats 
Cat.prototype.generalName = 'tiddles'; 

//this method is shared by all cats and has no access to private vars 
Cat.prototype.sayname = function(type) { 
    alert(this[type+'Name'] || 'private!'); 
} 

var vic = new Cat('Victor'); 
var ellers = new Cat('Elmore'); 

vic.sayname('general'); //tiddles 
vic.sayname('given');  //Victor 
vic.sayname('private'); //private - no access 
vic.sayPrivateName();  //cat will say its name 

ellers.sayname('general'); //tiddles 
ellers.sayname('given');  //Elmore 
ellers.sayname('private'); //private - no access 
ellers.sayPrivateName();  //cat will say its name 
+0

Nota: si su constructor devuelve algo (como un objeto, para exponer funciones o valores), entonces todos los miembros que declaró con 'this' ya no serán visibles públicamente. En otras palabras, en un constructor, adhiérete a 'this' o devuelve un' object' - normalmente no haces ambas cosas. – Matt

1

A (no tan) pequeña observación sobre las variables 'privado' en la asignación de los métodos al prototipo:

Es cierto que se no puede usar el constructor para crear un cierre sobre sus variables, pero puede rodear los métodos prototípicos con una función anónima y obtener las variables privadas compartidas entre las instancias del objeto:

function Foo() {} 

(function() { 
    var sharedPrivateVar; 
    Foo.prototype.methodWithAccessToSharedPrivateVar = function() {}; 
})(); 

Con un poco más haciendo girar, puede implementar sus propios mecanismos de protección, por ejemplo, qué variables sólo pueden ser leídos, no está escrito a través de:

function Foo() { 
    this.registerInstance({ bar : 'baz' }); 
    this.registerInstance = undefined; 
} 

(function() { 
    var store = {}, guid = 0; 

    Foo.prototype.registerInstance = function(protectedProperties) { 
     this.__guid = ++guid; 
     store[this.__guid] = protectedProperties; 
    }; 

    Foo.prototype.getProtectedProperty = function(name) { 
     return store[this.__guid][name]; 
    }; 

})(); 

Este enfoque no sufrirá de extensa objeto de función y la creación de cierre, pero aumenta los tiempos de búsqueda en una pequeña cantidad.

Editar: También debe proporcionar una función

Foo.prototype.unregisterInstance = function() { 
    delete store[this.__guid]; 
}; 

De lo contrario, esta es una buena manera de introducir una pérdida de memoria ...

Edit2: También puede moverse por la necesita una función registerInstance() con el siguiente patrón:

Foo = (function() { 
    var store = {}, guid = 0; 

    function Foo() { 
     this.__guid = ++guid; 
     store[guid] = { bar : 'baz' }; 
    } 

    Foo.prototype.getBar = function() { 
     var privates = store[this.__guid]; 
     return privates.bar; 
    }; 

    Foo.prototype.destroy = function() { 
     delete store[this.__guid]; 
    }; 

    return Foo; 
})(); 
Cuestiones relacionadas