Este código es de https://javascript.info/object-copy

function cloneDeep(obj) {
  let clone = {};
  for (let key in obj) {
    if (typeof obj[key] === "object") {
      clone[key] = cloneDeep(obj[key]);
    } else {
      clone[key] = obj[key];
    }
  }
  return clone;
}

let user = {
  name: "John",
  sizes: {
    height: 182,
    width: 50,
  },
};

console.log(cloneDeep(user));

No entiendo muy bien cómo funciona esta recursividad en la línea 5. Para cada tecla en obj (es decir, altura y tamaño), si hay un objeto dentro de un objeto, se ejecuta cloneDeep() nuevamente CADA VEZ . En la línea 2, vuelve a inicializar clone = {}.

No puedo entender por qué la salida no es algo como esto si se ejecuta cloneDeep() tanto para la altura como para la anchura:

{name: "John",
  sizes: {height: 182},
  sizes: {width: 50}
}
0
Julian 14 mar. 2021 a las 01:19

3 respuestas

La mejor respuesta

Debería pensar en esto como un problema de estructura de datos de árbol, un objeto tiene x propiedades secundarias, cada propiedad secundaria tiene x más propiedades secundarias, y así sucesivamente ... Para cada niño, hay un subárbol específico que este niño genera, por lo que puede Llame de forma recursiva a esta función para cada niño, ya que cada niño tiene su propio árbol de propiedades. Para comprender mejor este tipo de algoritmo, debe consultar los Trees.

3
leodavinci1 13 mar. 2021 a las 22:37

Una representación figurativa de lo que está sucediendo allí

let user = {      // is object, init cloneDeep0.clone0:{}
  name: "John",   // not object, set clone0 key/value         clone0={name: "John"}
  sizes: {        // is object, init cloneDeep1.clone1:{}
                  // set clone0 key/(clone1={}),              clone0={name: "John", sizes: (clone1={}}}
    height: 182,  // not object, set clone1 key/value         clone0={name: "John", sizes: (clone1={height: 182})}
    width: 50,    // not object, set clone1 key/value         clone0={name: "John", sizes: (clone1={height: 182, width: 50})}
  },
};
                  // return clone0={name: "John", sizes: (clone1={height: 182, width: 50})}

De hecho, hay un error en ese código, clonará los valores de null como {}

0
syduki 13 mar. 2021 a las 23:29

Considere una función clone que activa correctamente tanto Objetos como Matrices -

function clone(t)
{ switch(t?.constructor)
  { case Array:
      return t.map(v => clone(v))
    case Object:
      return Object
        .entries(t)
        .reduce
          ( (r, [k, v]) =>
              Object.assign(r, {[k]: clone(v)})
          , {}
          )
    default:
      return t
  }
}

Ahora configuramos un objeto original y un copy de ese objeto -

const original =
  {a: [{b:1}, {c:2}], d: {e: "f"}}
  
const copy =
  clone(original)

Si hacemos algunos cambios en original -

original.a[0].b = 11
original.a[1].c = 22
original.a.push({z:3})
original.d.e = "ff"

No deberían estar presentes en copy -

console.log(original)
// {"a":[{"b":11},{"c":22},{"z":3}],"d":{"e":"ff"}}

console.log(copy)
// {"a":[{"b":1},{"c":2}],"d":{"e":"f"}}

Expanda el fragmento a continuación para verificar los resultados en su propio navegador:

function clone(t)
{ switch(t?.constructor)
  { case Array:
      return t.map(v => clone(v))
    case Object:
      return Object
        .entries(t)
        .reduce
          ( (r, [k, v]) =>
              Object.assign(r, {[k]: clone(v)})
          , {}
          )
    default:
      return t
  }
}

const original =
  {a: [{b:1}, {c:2}], d: {e: "f"}}
  
const copy =
  clone(original)

// changes to original
original.a[0].b = 11
original.a[1].c = 22
original.a.push({z:3})
original.d.e = "ff"

console.log(JSON.stringify(original))
// {"a":[{"b":11},{"c":22},{"z":3}],"d":{"e":"ff"}}

console.log(JSON.stringify(copy))
// {"a":[{"b":1},{"c":2}],"d":{"e":"f"}}
0
Thank you 14 mar. 2021 a las 00:53