2011-06-13 15 views
6

Estoy intentando tener un objeto principal que puedo crear varias instancias de, que cada heredar los hijos (con propiedades únicas/aisladas). Sin embargo, cuando hago esto, las propiedades del objeto (después de haber sido modificado) cambian para todos los objetos creados. Puede que no esté explicando esto correctamente, pero el ejemplo debería ser bastante claro.OOP Javascript - Aislar objeto dentro de la clase

Main = function(){}; 

// Extending the main class with new object. Doing it this way so I can have these in 
// separate files. 
Main.prototype.foo = { 
    bar: 1 
} 

// First instance of Main(). 
var A = new Main(); 

// Second instance of Main(). 
var B = new Main(); 

// Set the bar property to different values for each Main() object. 
A.foo.bar = 2; 
B.foo.bar = 3; 

// Both A.foo.bar and B.foo.bar return 3. 
alert(A.foo.bar); 
alert(B.foo.bar); 

Lo que estoy tratando de conseguir que suceda, es para A.foo.bar para volver B.foo.bar 2 y 3 para volver, por lo que he aislado objetos que son independientes entre sí .

¿Alguna idea? ¿Me estoy perdiendo algo que es obvio? Sería muy apreciado!

+1

¿Por qué tiene la configuración para "foo" dos veces? ¿Es solo un error de transcripción? – Pointy

Respuesta

5

La propiedad "foo" está en el objeto prototipo, y solo hay una de ellas. Cuando lo configura en cualquier instancia, está afectando a esa misma propiedad compartida.

Usted puede agregar una propiedad de instancia en su constructor:

function Main() { 
    this.instanceProperty = 1; 
    } 

Entonces eso será por instancia.

El prototipo no es una "plantilla maestra" ni nada por el estilo; es un objeto real No se copia en instancias. En su lugar, el tiempo de ejecución sabe que está allí, y cuando se hacen referencias a propiedades en una instancia que en realidad no existe en la instancia, entonces sabe subir la cadena del prototipo y buscar propiedades allí.

1

Como está editando algo en el prototipo, va a afectar a todos los objetos.

Sin embargo, se puede hacer:

A.x = 2; 
B.x = 3; 

entonces usted tendrá resultados diferentes.

O bien, puede tener algo como esto:

Main = function(val){ 
    this.x = val; 
} 

A = new Main(2); 
B = new Main(3); 
3

Las otras respuestas son más o menos correcta, pero lo que se pierden es que hay una diferencia entre

Main.prototype.foo = { 
    bar: 1 
}; 

y

Main.prototype.bar = 1; 

En ambos casos, crear una nueva instancia Main creará una nueva instancia con, en su cadena de prototipo, una propiedad foo o bar. En ambos casos, la propiedad a nivel de instancia se puede redefinir sin afectar a otras instancias:

function Main() {}; 
Main.prototype.foo = { 
    bar: 1 
}; 
Main.prototype.bar = 1; 

a = new Main(); 
b = new Main(); 

a.foo = { bar: 2 }; 
console.log(a.foo.bar, b.foo.bar); // 2 1 

a.bar = 2; 
console.log(a.bar, b.bar); // 2 1 

Pero cuando se instancia un nuevo Main, la variable de instancia foo es una referencia a un único objeto, {bar:1}, que es compartido entre todas las instancias. Entonces cuando configura a.foo.bar, está cambiando el objeto común, no una variable de instancia; la variable de instancia es la referencia a.foo.

No tiene que inicializar la propiedad de la instancia en el constructor. El enfoque estándar sería establecer bar directamente en el prototipo, es decirMain.prototype.bar = 1, que le daría variables de instancia independientes inicializadas en 1. Sin embargo, si necesita una estructura de datos más compleja (un objeto, una matriz o una instancia de otra clase) por instancia, no puede crear esto como una propiedad en el prototipo, porque estará dando a cada instancia una referencia a un objeto común, entonces dentro del constructor está el camino a seguir:

function Main() { 
    // instance-level object 
    this.foo = { 
     bar: 1 
    }; 
} 
+3

Consulte esta excelente publicación para comprender claramente cómo funcionan los prototipos: https://javascriptweblog.wordpress.com/2010/06/07/understanding-javascript-prototypes/ – rahulmohan

+0

Creo que la declaración "variable de instancia foo es una referencia a un solo objeto "es importante entender el comportamiento de manipular un atributo dentro de foo. – maulik13

Cuestiones relacionadas