Tengo una variable que tiene un objeto JSON como valor. Asigno directamente esta variable a alguna otra variable para que compartan el mismo valor. Así es como funciona:
var a = $('#some_hidden_var').val(),
b = a;
Esto funciona y ambos tienen el mismo valor. Utilizo un mousemovecontrolador de eventos para actualizar bmi aplicación. Al hacer clic en un botón, quiero volver bal valor original, es decir, el valor almacenado en a.
$('#revert').on('click', function(e){
b = a;
});
Después de esto, si uso el mismo mousemovecontrolador de eventos, actualiza ambos ay b, cuando antes, se actualizaba solo bcomo se esperaba.
¡Estoy perplejo por este problema! ¿Que esta mal aquí?
javascript
jquery
Rutwick Gangurde
fuente
fuente

ase configuró desde.val(), supongo que es JSON (una cadena), no un objeto, ¿es así? ¿UsasJSON.parse(a)en algún momento para obtener un objeto real?$.parseJSONpara convertirla en un objeto. Estructura:{ 'key': {...}, 'key': {...}, ...}. Lo siento, no puedo publicar ningún código aquí, ¡no está permitido en mi lugar de trabajo!aun objeto?auna variable global?$.parseJSON()entra?) Es difícil decir cuál es el problema. Con respecto a las reglas de su lugar de trabajo, no tiene que publicar su código real real en su totalidad, solo presente un ejemplo más corto y más genérico que demuestre el problema (e, idealmente, incluya un enlace a una demostración en vivo en jsfiddle.net ) .Respuestas:
Es importante comprender qué
=hace y qué no hace el operador en JavaScript.El
=operador no realiza una copia de los datos.El
=operador crea una nueva referencia a los mismos datos.Después de ejecutar su código original:
aybahora son dos nombres diferentes para el mismo objeto .Cualquier cambio que realice en el contenido de este objeto se verá de manera idéntica ya sea que haga referencia a él a través de la
avariable o labvariable. Son el mismo objeto.Entonces, cuando más tarde intente "volver"
balaobjeto original con este código:El código en realidad no hace nada en absoluto , porque
aybson exactamente lo mismo. El código es el mismo que si hubiera escrito:que obviamente no hará nada.
¿Por qué funciona tu nuevo código?
Aquí está creando un objeto nuevo con el
{...}objeto literal. Este nuevo objeto no es el mismo que su antiguo objeto. Así que ahora estás configurandobcomo referencia a este nuevo objeto, que hace lo que quiere.Para manejar cualquier objeto arbitrario, puede usar una función de clonación de objetos como la que se enumera en la respuesta de Armand, o como está usando jQuery, simplemente use la
$.extend()función . Esta función hará una copia superficial o una copia profunda de un objeto. (No confunda esto con el$().clone()método que es para copiar elementos DOM, no objetos).Para una copia superficial:
O una copia profunda:
¿Cuál es la diferencia entre una copia superficial y una profunda? Una copia superficial es similar a su código que crea un nuevo objeto con un objeto literal. Crea un nuevo objeto de nivel superior que contiene referencias a las mismas propiedades que el objeto original.
Si su objeto contiene solo tipos primitivos como números y cadenas, una copia profunda y una copia superficial harán exactamente lo mismo. Pero si su objeto contiene otros objetos o matrices anidadas dentro de él, entonces una copia superficial no copia esos objetos anidados, simplemente crea referencias a ellos. Entonces, podría tener el mismo problema con los objetos anidados que tenía con su objeto de nivel superior. Por ejemplo, dado este objeto:
Si hace una copia superficial de ese objeto, entonces la
xpropiedad de su nuevo objeto es el mismoxobjeto del original:Ahora sus objetos se verán así:
Puede evitar esto con una copia profunda. La copia profunda se repite en cada objeto y matriz anidados (y Fecha en el código de Armand) para hacer copias de esos objetos de la misma manera que hizo una copia del objeto de nivel superior. Así que cambiar
copy.x.yno afectaríaobj.x.y.Respuesta corta: en caso de duda, probablemente desee una copia detallada.
fuente
$.extend()función incorporada. Detalles arriba. :-)Encontré que usar JSON funciona, pero observe nuestras referencias circulares
fuente
let a = {}; let b = {a:a}; a.b = b; JSON.stringify(a)dará un TypeErrorla pregunta ya está resuelta desde hace bastante tiempo, pero para referencia futura una posible solución es
Tenga cuidado, esto funciona correctamente solo si a es una matriz no anidada de números y cadenas
fuente
newVariable = originalVariable.valueOf();para los objetos que puedes usar,
b = Object.assign({},a);fuente
La razón de esto es simple. JavaScript usa referencias, por lo que cuando asigna
b = a, está asignando una referencia a, por lobtanto, al actualizara, también está actualizandobEncontré esto en stackoverflow y ayudaré a prevenir cosas como esta en el futuro simplemente llamando a este método si desea hacer una copia profunda de un objeto.
fuente
if (obj instanceof x) { ... }si?No entiendo por qué las respuestas son tan complejas. En Javascript, las primitivas (cadenas, números, etc.) se pasan por valor y se copian. Los objetos, incluidas las matrices, se pasan por referencia. En cualquier caso, la asignación de un nuevo valor o referencia de objeto a 'a' no cambiará 'b'. Pero cambiar el contenido de 'a' cambiará el contenido de 'b'.
Pegue cualquiera de las líneas anteriores (una a la vez) en el nodo o en cualquier consola javascript del navegador. Luego escriba cualquier variable y la consola mostrará su valor.
fuente
Para cadenas o valores de entrada, simplemente puede usar esto:
fuente
La mayoría de las respuestas aquí usan métodos integrados o bibliotecas / marcos. Este método simple debería funcionar bien:
fuente
Object.assign({},a)Lo resolví yo mismo por el momento. El valor original tiene solo 2 subpropiedades. Reformé un nuevo objeto con las propiedades de
ay luego se lo asignéb. Ahora mi controlador de eventos solo se actualizab, y mi originalapermanece como está.Esto funciona bien. No he cambiado una sola línea en ningún lugar de mi código, excepto lo anterior, y funciona exactamente como quería. Entonces, créame, nada más se estaba actualizando
a.fuente
Una solución para AngularJS :
fuente