La modificación de una copia de un objeto JavaScript hace que el objeto original cambie

Resuelto Vallabha asked hace 9 años • 13 respuestas

estoy copiando objAaobjB

const objA = { prop: 1 }, 
const objB = objA; 
objB.prop = 2;
console.log(objA.prop); // logs 2 instead of 1

mismo problema para matrices

const arrA = [1, 2, 3], 
const arrB = arrA; 
arrB.push(4); 
console.log(arrA.length); // `arrA` has 4 elements instead of 3.
Vallabha avatar Mar 14 '15 21:03 Vallabha
Aceptado

Está claro que tiene algunas ideas erróneas sobre lo que var tempMyObj = myObj;hace la declaración.

En JavaScript, los objetos se pasan y asignan por referencia (más exactamente, el valor de una referencia), por lo que tempMyObjy myObjson ambas referencias al mismo objeto.

Aquí tienes una ilustración simplificada que puede ayudarte a visualizar lo que está sucediendo.

// [Object1]<--------- myObj

var tempMyObj = myObj;

// [Object1]<--------- myObj
//         ^ 
//         |
//         ----------- tempMyObj

Como puede ver después de la tarea, ambas referencias apuntan al mismo objeto.

Debe crear una copia si necesita modificar uno y no el otro.

// [Object1]<--------- myObj

const tempMyObj = Object.assign({}, myObj);

// [Object1]<--------- myObj
// [Object2]<--------- tempMyObj

Antigua respuesta:

Aquí hay un par de formas más de crear una copia de un objeto.

Como ya estás usando jQuery:

var newObject = jQuery.extend(true, {}, myObj);

Con JavaScript básico

function clone(obj) {
    if (null == obj || "object" != typeof obj) return obj;
    var copy = obj.constructor();
    for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
    }
    return copy;
}

var newObject = clone(myObj);

Ver aquí y aquí

robbmj avatar Mar 14 '2015 14:03 robbmj

Para resumir todo y para aclarar, hay cuatro formas de copiar un objeto JS.

  1. Una copia normal . Cuando cambia las propiedades del objeto original, las propiedades del objeto copiado también cambiarán (y viceversa).
const a = { x: 0}
const b = a;
b.x = 1; // also updates a.x
  1. Una copia superficial . Las propiedades de nivel superior serán únicas para el objeto original y copiado. Sin embargo, las propiedades anidadas se compartirán entre ambos objetos. Utilice el operador de extensión ...{}o Object.assign().
const a = { x: 0, y: { z: 0 } };
const b = {...a}; // or const b = Object.assign({}, a);

b.x = 1; // doesn't update a.x
b.y.z = 1; // also updates a.y.z
  1. Una copia profunda . Todas las propiedades son únicas para el objeto original y copiado, incluso las propiedades anidadas. Para una copia profunda, serialice el objeto en JSON y analícelo nuevamente en un objeto JS.
const a = { x: 0, y: { z: 0 } };
const b = JSON.parse(JSON.stringify(a)); 

b.y.z = 1; // doesn't update a.y.z
  1. Una copia completa y profunda . Con la técnica anterior, se descartarán los valores de propiedad que no sean válidos en JSON (como funciones). Si necesita una copia profunda y mantener propiedades anidadas que contienen funciones, es posible que desee buscar en una biblioteca de utilidades como lodash.
import { cloneDeep } from "lodash"; 
const a = { x: 0, y: { z: (a, b) => a + b } };
const b = cloneDeep(a);

console.log(b.y.z(1, 2)); // returns 3
  1. El uso Object.create()crea un nuevo objeto. Las propiedades se comparten entre objetos (cambiar uno también cambia el otro). La diferencia con una copia normal es que las propiedades se agregan bajo el prototipo del nuevo objeto __proto__. Cuando nunca cambias el objeto original, esto también podría funcionar como una copia superficial, pero sugeriría usar uno de los métodos anteriores, a menos que necesites específicamente este comportamiento.
jnaklaas avatar Jul 06 '2021 11:07 jnaklaas

objeto de clonación profunda con JSON.parse() y JSON.stringify

// Deep Clone
obj = { a: 0 , b: { c: 0}};
let deepClone = JSON.parse(JSON.stringify(obj));

referencia: este artículo

Mejor referencia : este artículo.

Ahmed El Damasy avatar Sep 26 '2019 08:09 Ahmed El Damasy