2009-11-30 13 views
10

Soy relativamente nuevo en JS y tengo problemas para emular los principios de OOP.Clases de JavaScript y ámbito variable

Supongo que tengo dos preguntas. La primera pregunta es sobre las muchas formas de declarar variables.

Decir que tengo una clase:

function clazz(a) 
{ 
    this.b = 2; 
    var c = 3; 
    this.prototype.d = 4; // or clazz.prototype.d = 4? 
} 

var myClazz = new clazz(1); 

Estoy en lo correcto en las siguientes evaluaciones:

a es una variable privada que es instancia específica (es decir, diferentes instancias de clazz tendrán variables únicas e independientes 'un'). Se puede acceder desde clazz como: 'a'.

b es una variable pública que es específica de la instancia. Se puede acceder desde dentro de clazz como 'this.b' y desde clazz externo como 'myClazz.b'.

c es una variable privada que es estática, o clase específica (es decir, distintas instancias de clazz compartirán la misma variable 'c'). Se puede acceder desde cualquier instancia de clazz como 'c' y los cambios en la instancia de clazz se reflejan en todas las instancias de clazz.

d es una variable pública que es estática/clase específica. Se puede acceder desde cualquier lugar a través de 'clazz.prototype.d' o 'myClazz.prototype.d'.

El problema general que tengo con mi comprensión del esquema de variables es que no hay forma de declarar una variable privada que NO sea estática (es decir, una versión única para cada instancia de la clase).

La segunda pregunta es con respecto a los diferentes tipos de declaraciones de clase.

He estado usando:

var MySingleton = new function() {...}; 

para crear conjuntos unitarios. ¿Es esto correcto? También estoy seguro sobre el efecto de la "nueva" palabra clave en esta situación, así como anexar() la función de los apoyos hasta el final de la declaración como tal:

var MySingleton = new function() {...}(); 

He estado usando este patrón de declare una clase y luego crea instancias de esa clase:

function myClass() {...}; 
var classA = new myClass(); 
var classB = new myClass(); 

¿Es este el método correcto?

Respuesta

18

usted tiene razón para a y b:

a es un argumento, disponible sólo en el ámbito de la constructor function.

b es una variable de instancia pública, disponible en todas las instancias creadas con esa función de constructor.

c es una variable privada, accesible solo dentro de la función de constructor.

La declaración d no es válido, porque el objeto prototype está destinado a ser utilizado únicamente en constructor functions, como Clazz.prototype.d = 3;, si lo haces de esta manera, se compartirá la variable, pero se puede asignar un valor a una instancia específica, y el valor predeterminado será sombreado (a través de la cadena de prototipos).

Por "variables privadas" que pueden utilizarse para la declaración de c, por ejemplo: métodos

function Clazz(){ 
    var c = 3; // private variable 

    this.privilegedMethod = function() { 
     alert(c); 
    }; 
} 

privilegiado, son públicos, pero pueden acceder a las variables "privadas" declaradas dentro de la función constructora.

Para la creación de embarazos únicos, la forma más fácil es tal vez de usar un objeto literal, como:

var myInstance = { 
    method1: function() { 
    // ... 
    }, 
    method2: function() { 
    // ... 
    } 
}; 

Y si desea que los miembros privados en su instancia Singleton, puede:

var myInstance = (function() { 
    var privateVar = ''; 

    function privateMethod() { 
    // ... 
    } 

    return { // public interface 
    publicMethod1: function() { 
     // all private members are accesible here 
    }, 
    publicMethod2: function() { 
    } 
    }; 
})(); 

Este se ha denominado patrón de módulo, básicamente le permite encapsular miembros privados en un objeto, aprovechando el uso de closures.

Más información:

Editar: sobre la sintaxis de publicar:

var mySingleton = new (function() { 
    // ... 
})(); 

Al utilizar el operador new, estás diciembre Usando un paso "constructor anónimo función", que generará una nueva instancia de objeto, es válido pero yo personalmente preferiría el enfoque de patrón "módulo" para crear mi propia instancia de objeto (y evitar new)

Además, la lectura de new function() {}, creo que no es muy intuitivo y puede crear confusión, si no entiende bien cómo funciona el operador new.

Acerca de los paréntesis, que son opcionales, el operador new se llama al constructor función sin parámetros si no añadirlos (ver ECMA-262, 11.2.2).

+2

+1. Una respuesta muy completa e informativa. –

+0

Gracias por la respuesta informativa. Un seguimiento: ¿Cuáles son las diferencias tangibles entre el enfoque de módulo a la declaración singleton y el estilo al que se hace referencia en la publicación original? – Cmc

+0

** @ Lior: ** gracias! ** Cmc: ** Escribí un poco sobre la sintaxis que publicaste ... – CMS

3

OK, vamos a repasar esto:

  1. 'a' es un argumento pasado al constructor de la clase. Solo existirá mientras dure la invocación del constructor. Esto significa que probablemente debas almacenar su valor en alguna parte.

  2. 'b' es un miembro público de la instancia. Es específico de la instancia (aunque, ya que está asignando el valor en el constructor, todas las instancias tendrán inicialmente el mismo valor para 'b').

  3. 'c' es un miembro de instancia privada. Sin embargo, solo será accesible dentro de su constructor ya que solo está definido en ese alcance. A menos que se refiera a él desde un cierre dentro de su función de constructor, su destino será similar al de 'a' anterior.

  4. 'd' es un miembro de instancias públicas. Cada instancia de su clase tendrá un miembro 'd' con el valor 4 inicialmente. Sin embargo, tenga en cuenta que asignar un objeto de tipo de referencia a un miembro prototipo de su clase (como 'd') hará que cada miembro de la instancia 'd' se refiera al mismo objeto. Ejemplo:

    MyClass.prototype.d = { prop1: 'val1', prop2: 'val2' };   
    var a = new MyClass(); 
    var b = new MyClass();   
    a.d.prop1 = 'foo'; // is the same as: b.d.prop1 = 'foo'; 
    
  5. miembros estáticos de la clase se definen mediante:

    function MyClass() 
    { 
        // ... 
    }  
    MyClass.staticMemeber = 'I am a static member'; 
    

    Probablemente no debería tratar MyClass.prototype como un lugar para celebrar su miembros estáticos/methods.Everything asignado a una clases 'prototipo es a su vez un miembro de cada una de sus instancias.

  6. Cuando los() están adjuntos a una definición de función (justo después del bloque), la función se ejecuta. Eso significa:

    var myFunc = function() { alert('blah'); }(); 
    

    resultaría en nada más que una invocación al método. El siguiente código:

    var MySingleton = new function() {...}(); 
    

    significaría 'utilizar el valor de retorno de la función() como el constructor de MySingleton'.

Cuestiones relacionadas