Maneras de clonar un objecto in javascript

Ya que los objetos en javascript son valores por referencencia, no pueden copiarse simplemente con el =. Aqui os dejo diferentes maneras de hacerlo.

let profesiones = { medico: '🚑', policia: '🚓', bombero: '🚒' }

// "Spread operator"
let clone_one = { ...profesiones }
console.log(clone_one) 
// clone_one { medico: '🚑', policia: '🚓', bombero: '🚒' }

// "Object.assign
let clone_two = Object.assign({}, profesiones)
console.log(clone_two) 
// clone_two { medico: '🚑', policia: '🚓', bombero: '🚒' }

// "JSON"
let clone_three = JSON.parse(JSON.stringify(profesiones))
console.log(clone_three) 
// clone_three { medico: '🚑', policia: '🚓', bombero: '🚒' }


Los objetos son tipo reference



Si utilizamos el operator de asignación pasa lo siguiente

const obj = { one: 1, two: 2 }

const obj2 = obj

console.log(
  obj, // {one: 1, two: 2}
  obj2, // {one: 1, two: 2}
);


En principio es todo correcto, el problema viene cuando editamos por ejemplo el segundo objeto

const obj2.three = 3;

console.log(obj2);
// {one: 1, two: 2, three: 3} <- ✅

console.log(obj);
// {one: 1, two: 2, three: 3} <- 😱


Al ser objetos que van por tipo de reference, cuando asignas '=' también copyas el puntero al espacio de memoria que ocupa. Los tipos de referencencia no contienen valores, son un puntero al valor en la memoria.

확산 연산자



El uso del spread operator clonará el objecto, pero es una copya superficial del mismo.

let profesiones = { medico: '🚑', policia: '🚓', bombero: '🚒' }

let clone_spread = { ...profesiones }

console.log(clone_spread)
// clone_spread { medico: '🚑', policia: '🚓', bombero: '🚒' }


우산도 Object.assign



Esta opción tambien creará una copy superficial del objeto.

let profesiones = { medico: '🚑', policia: '🚓', bombero: '🚒' }

let object_assign = Object.assign({}, profesiones)

console.log(object_assign)
// object_assign { medico: '🚑', policia: '🚓', bombero: '🚒' }


Tener en cuenta el primer argumento {}, esto asegurará que no mute el objeto original

우산도 JSON



Está manera si que dará una copya profunda. Aunque es una manera sucia de hacerlo, pero rápida.

let profesiones = { medico: '🚑', policia: '🚓', bombero: '🚒' }

let clone_json = JSON.parse(JSON.stringify( profesiones))

console.log(clone_json)
// clone_json { medico: '🚑', policia: '🚓', bombero: '🚒' }


Utilizando librerias externa lodash



DeepClone funciona con todos los tipos, funciones y símbolos, se copor por reference

const lodashClonedeep = require('lodash.clonedeep')

let profesiones = { medico: '🚑', policia: '🚓', bombero: '🚒' }

let clone_lodash = lodashClonedeep(profesiones);

console.log(clone_lodash)
// clone_lodash { medico: '🚑', policia: '🚓', bombero: '🚒' }


라이브러리는 참조할 때 참조할 수 있는 기능과 기호를 모두 포함할 수 있습니다.

const lodashClonedeep = require('lodash.clonedeep')

const arrOfFunction = [
  () => 2,
  {
    test: () => 3,
  },
  Symbol('4'),
];

// deepClone copy by refence function and Symbol
console.log(lodashClonedeep(arrOfFunction))
// [ [Function (anonymous)], { test: [Function: test] }, Symbol(4) ]

// JSON replace function with null and function in object with undefined
console.log(JSON.parse(JSON.stringify(arrOfFunction)))
// [ null, {}, null ]

// function and symbol are copied by reference in deepClone
console.log(
  lodashClonedeep(arrOfFunction)[0] === lodashClonedeep(arrOfFunction)[0],
)
// true

console.log(
  lodashClonedeep(arrOfFunction)[2] === lodashClonedeep(arrOfFunction)[2],
)
// true


El método JSON tiene problemas con las dependsencias circulares. Además, el orden de las propiedades en el objeto clonado puede ser diferente.

Cuando utilizar una clone superficial 또는 profundo



Si utilizamos el spread operator, para copuar un objeto, solo se copyia superficialmente, si la matriz está anidada o es multidimensional, no funcionará correctamente

const nestedObject = {
    name: 'batman',
    country: {
      city: 'gotam'
    }
}


A. 복사 표면

Clonamos el objeto y lo modificamos

const shallowClone = { ... nestedObject }

// modificamos los valores.
shallowClone.name = 'superman'
shallowClone.country.city = 'metropolis'

console.log(shallowClone);
// {name: 'superman', {city: 'metropolis'}}

console.log(nestedObject);
// {name: 'batman', {city: 'metropolis'}} <- 😱


Una copya superficial significa que se copia el primer nivel, se hace reference a los niveles más profundos.
En temas de perfomance decir que Object.assign es mucho más rápido que JSON.

B. Copia Profunda

Tomemos el mismo ejemplo pero aplicando una copyia profunda usando JSON

const deepClone = JSON.parse(JSON.stringify(nestedObject));

console.log(deepClone);
// {name: 'superman', {city: 'metropolis'}}

console.log(nestedObject);
// {name: 'batman', {city: 'gotam'}}



Como puede ver, la copia profunda es una copia fiel de los objetos anidados. A menudo, la copya superficial es lo suficientemente buena, realmente no necesita una copia profunda.

좋은 웹페이지 즐겨찾기