2012-02-27 20 views
5

entiendo la siguiente propiedad del lenguaje javascript:Javascript confusión sobre las variables definidas por referencia vs valor

var bar = 1; 
var foo = bar; 
bar = "something entirely different"; 
// foo is still 1 

Sin embargo, cuando se trata de aplicar esta lógica a un objeto que parece actuar de manera diferente:

var bar = {}; 
bar.prop = 1; 
var foo = bar; 
bar.prop = "something entirely different"; 
// foo.prop now changes to "something entirely different" 
// but... 
bar = "no longer an object"; 
// now foo remains an object with the prop property 

¿Puede alguien decirme qué está pasando y por qué hay una diferencia?

+3

Pude haber respondido a mi propia pregunta: "Javascript siempre pasa por valor, pero cuando una variable hace referencia a un objeto (incluidas las matrices), el" valor "es una referencia al objeto." Pero esto todavía es confuso, ¿alguien puede explicar más? – Jeff

+0

Ver mi respuesta Jeff, por favor, avíseme si tiene algún sentido. – Josh

+0

posible duplicado de [¿Es Java pasar por referencia?] (Http://stackoverflow.com/questions/40480/is-java-pass-by-reference) –

Respuesta

1

Eso es correcto. Cuando asigna una variable a un objeto, realmente está creando una segunda referencia a ese objeto. En el primer caso, lo que está haciendo es asignar bar para apuntar a la cadena foo puntos, pero entonces cambia a lo que apunta bar al reasignar bar.

En el segundo ejemplo, se asignan bar a un nuevo objeto, a continuación, se señala foo en ese mismo objeto, a continuación, reasigna bar en una cadena. foo sigue apuntando al mismo objeto.

Piense en ello como esto: bar = "something" es cambiando lo bar puntos a, sin cambiar el objeto real {} en una cadena.

This article es una buena explicación de lo que está viendo. Estoy buscando referencias aún mejores/más autorizadas, sin embargo.

+1

Esto es lo que iba a decir, la memoria que contenía el objeto 'bar' se asignó a no se borró y se reemplazó con' "ya no es un objeto" 'pero se quitó la referencia (y si no tuviera otras referencias lo haría estar en cola para la recolección de basura). –

0

En el primer código, define la barra Var como variable.

en el segundo código lo define como un objeto.

Las variables tienen un lugar en la memoria, por lo que cuando se define foo desde la barra, será del mismo tipo que la variable y se reservará una nueva ubicación de memoria; y cuando usa un operador igual, está reemplazando el contenido de datos de esta variable.

El objeto en el segundo código de muestra al inicializar apuntará (como puntero) a una ubicación de memoria que contendrá los datos de este objeto; y cuando defina foo desde la barra, será del mismo tipo que el objeto y apuntará a la misma ubicación de memoria; así que cambiar uno de estos dos valores de objeto de referencia se reflejará en el otro.

1

Tomemos línea por línea:

var foo = bar; 

Todos los nombres de los objetos que hacer es mantener las direcciones en la memoria. Por lo tanto, en esta declaración, usted está haciendo que foo tenga la misma dirección de memoria que bar. Si, por ejemplo, bar tenía 0xFF, entonces a través de la asignación haría foo también mantener 0xFF.

Sin embargo, tenga en cuenta que bar y foo son dos objetos distintos, por casualidad mantienen la misma dirección en la memoria.

Ahora, ya que tienen la misma dirección en la memoria, mutar miembros de bar también afectará a los miembros de foo porque están vinculados al mismo objeto.

bar.prop = "something entirely different"; // affects foo.prop also 

Sin embargo, aquí está el punto clave a recordar:

Assignment only changes what the name of the object is bound to, and does not affect any other objects.

En otras palabras, la siguiente declaración hecha bar sostienen una dirección de memoria diferente, pero esto no afecta a foo.

bar = "no longer an object"; // Made bar hold a different memory address 

Ahora, explicando la cita:

Javascript is always pass by value, but when a variable refers to an object (including arrays), the "value" is a reference to the object.

Tome este ejemplo:

function f(obj1, obj2) 
{ 
    obj1.prop = 10; 
    obj2 = {prop: 20}; 
} 

var bar = {prop: 1}; 
var foo = {prop: 2}; 
f(bar, foo); 
console.log("bar.prop: " + bar.prop + ", foo.prop: " + foo.prop); 

Esto imprime outs: bar.prop: 10, foo.prop: 2. Dentro de la función f, obj1 tiene la misma dirección de memoria que bar y obj2 tiene la misma dirección de memoria que foo. Sin embargo, solo la barra se ve afectada porque dentro de f solo se reflejan los elementos alterados de los objetos y la asignación obj2 = {prop: 20}; solo afecta a la variable local obj2 no a foo.

En otras palabras, the "value" is a reference to an object significa que modificar miembros afecta al objeto referenciado, pero la asignación solo afecta a la variable local.

+0

Creo que esa es la explicación más confusa que he visto. Olvídate de la memoria y las direcciones, ECMA-262 especifica el comportamiento, no la implementación. – RobG

+0

@RobG: Creo que tiene más sentido lo concreto que el resumen (que era lo que estaba tratando de hacer), pero gracias por el comentario (me doy cuenta de que esto puede no ser apropiado para todos). Sin embargo, más comentarios * específicos * serían más beneficiosos para mí. –

Cuestiones relacionadas