Cómo clonar un objeto completamente

Fácil - 2 min. lectura

En javascript podemos copiar objetos de muchas formas, entre ellas Object.assign y mediante el spread operator.
Particularmente este último es el que más suelo usar:

const objeto = {name: "Javascript"}
const clon = {...objeto}
console.log(clon.name) // Javascript

Hasta aquí todo normal, pero nos encontramos un problema cuando los objetos a su vez tienen objetos dentro:

const js = {
  name: "Javascript",
  version: {
    name: "ES6"
  }
}
const lastVerion = {...js}
lastVerion.version.name = "ES2021"
console.log(lastVerion.version.name) // ES2021 👍
console.log(js.version.name) // ES2021 🤷

¿Qué ha pasado aquí?

Algo que debemos saber, es que tanto Object.assign como Spread Operator nos van a realizar una copia exacta pero sólo
para los objetos simples. Sin embargo, en los objetos complejos (con otros objetos dentro) nos hará shallow copy,
es decir, estos objetos interiores serán referencias a los objetos interiores del objeto inicial. Como podrás imaginarte,
esto puede ocasionarte muchos problemas y debemos tener cuidado.

¿Cómo hacemos un deep copy?

Quizás la forma más usada hasta ahora es usar un pequeño truco consistido en pasar a json y volver a pasarlo de nuevo a objeto mediante el objeto JSON

const js = {
  name: "Javascript",
  version: {
    name: "ES6"
  }
}
const lastVerion = JSON.parse(JSON.stringify(js))
lastVerion.version.name = "ES2021"
console.log(lastVerion.version.name) // ES2021 👍
console.log(js.version.name) // ES6 👍

En las últimas versiones de Javascript tenemos el método structuredClone que nos permite hacer esta copia profunda
sin recurrir al truco anterior.

const js = {
  name: "Javascript",
  version: {
    name: "ES6"
  }
}
const lastVerion = structuredClone(js)
lastVerion.version.name = "ES2021"
console.log(lastVerion.version.name) // ES2021 👍
console.log(js.version.name) // ES6 👍

Algo a tener en cuenta es que si nuestro objeto tiene funciones, estas formas no nos funcionarán y tendremos que
realizarlo nosotros mismos recorriendo el objeto de forma recursiva.