Así que estuve jugando el otro día solo para ver exactamente cómo funciona la asignación masiva en JavaScript.
Primero probé este ejemplo en la consola:
a = b = {};
a.foo = 'bar';
console.log(b.foo);
El resultado fue que se mostraba una "barra" en una alerta. Eso es bastante justo, a
y en b
realidad son solo alias para el mismo objeto. Luego pensé, ¿cómo podría simplificar este ejemplo?
a = b = 'foo';
a = 'bar';
console.log(b);
Eso es más o menos lo mismo, ¿no? Bueno, esta vez, devuelve foo
no bar
lo que cabe esperar del comportamiento del primer ejemplo.
¿Por qué pasó esto?
NB Este ejemplo podría simplificarse aún más con el siguiente código:
a = {};
b = a;
a.foo = 'bar';
console.log(b.foo);
a = 'foo';
b = a;
a = 'bar';
console.log(b);
(Sospecho que JavaScript trata las primitivas como cadenas y enteros de manera diferente a los hash. Los hash devuelven un puntero mientras que las primitivas "centrales" devuelven una copia de sí mismas)
fuente
Respuestas:
En el primer ejemplo, está configurando una propiedad de un objeto existente. En el segundo ejemplo, está asignando un objeto nuevo.
a
yb
ahora son punteros al mismo objeto. Entonces, cuando lo hagas:También establece
b.foo
desdea
yb
apunta al mismo objeto.¡Sin embargo!
Si haces esto en su lugar:
estás diciendo que ahora
a
apunta a un objeto diferente. Esto no tiene ningún efecto sobre loa
señalado antes.En JavaScript, asignar una variable y asignar una propiedad son 2 operaciones diferentes. Es mejor pensar en las variables como punteros a objetos, y cuando asigna directamente a una variable, no está modificando ningún objeto, simplemente re-apuntando su variable a un objeto diferente.
Pero asignar una propiedad, como
a.foo
, modificará el objeto al quea
apunta. Esto, por supuesto, también modifica todas las demás referencias que apuntan a este objeto simplemente porque todas apuntan al mismo objeto.fuente
var foo = new String('foo');
, entonces sería un objeto de cadena (y lo confirmará). Pero si lo declara a través de un literal de cadena, entonces son primitivas de cadena. Ver: developer.mozilla.org/en/JavaScript/Reference/Global_Objects/…typeof
Su pregunta ya ha sido respondida satisfactoriamente por Squeegy: no tiene nada que ver con objetos frente a primitivas, sino con reasignación de variables frente a establecer propiedades en el mismo objeto referenciado.
Parece haber mucha confusión sobre los tipos de JavaScript en las respuestas y comentarios, así que aquí hay una pequeña introducción al sistema de tipos de JavaScript:
En JavaScript, hay dos tipos de valores fundamentalmente diferentes: primitivos y objetos (y no hay nada como un 'hash').
Las cadenas, los números y los valores booleanos, así como
null
yundefined
son primitivos, los objetos son todo lo que puede tener propiedades. Incluso las matrices y las funciones son objetos regulares y, por lo tanto, pueden contener propiedades arbitrarias. Solo difieren en la propiedad interna [[Clase]] (las funciones además tienen una propiedad llamada [[Llamar]] y [[Construir]], pero bueno, eso es detalles).La razón por la que los valores primitivos pueden comportarse como objetos se debe al autoencuadre, pero los primitivos en sí mismos no pueden tener ninguna propiedad.
Aquí hay un ejemplo:
Esto dará como resultado
undefined
:a
contiene un valor primitivo, que se promueve a un objeto cuando se asigna la propiedadfoo
. Pero este nuevo objeto se descarta inmediatamente, por lo quefoo
se pierde el valor de .Piensa en esto, de esta manera:
fuente
Estás más o menos en lo correcto excepto que lo que te refieres como un "hash" es en realidad una sintaxis abreviada de un objeto.
En el primer ejemplo, un y b ambos se refieren al mismo objeto. En el segundo ejemplo, cambia a para hacer referencia a otra cosa.
fuente
aquí está mi versión de la respuesta:
fuente
Está configurando a para que apunte a un nuevo objeto de cadena, mientras que b sigue apuntando al antiguo objeto de cadena.
fuente
En el primer caso se cambia alguna propiedad del objeto contenido en la variable, en el segundo caso se asigna un nuevo valor a la variable. Eso son cosas fundamentalmente diferentes. Las variables
a
yb
no están vinculadas mágicamente de alguna manera por la primera asignación, solo contienen el mismo objeto. Ese también es el caso en el segundo ejemplo, hasta que asigne un nuevo valor a lab
variable.fuente
La diferencia está entre tipos y objetos simples.
Todo lo que sea un objeto (como una matriz o una función) se pasa por referencia.
Todo lo que sea de un tipo simple (como una cadena o un número) se copia.
Siempre tengo una función copyArray a mano para poder estar seguro de que no estoy creando un montón de alias para la misma matriz.
fuente