No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Aprende todo un fin de semana sin pagar una suscripci贸n 馃敟

Aprende todo un fin de semana sin pagar una suscripci贸n 馃敟

Reg铆strate

Comienza en:

0D
18H
23M
58S

Deep copy con recursividad

9/20
Recursos

Con el Deep Copy podemos generar copias de objetos sin importar que estos posean objetos anidados o m茅todos dentro.

Aplicando Deep Copy en JavaScript

Veamos el siguiente ejemplo:

// OBJETO ORIGINAL
const studentBase = {
  name: undefined,
  email: undefined,
  age: undefined,
  approvedCourses: undefined,
  learningPaths: undefined,
  socialMedia: {
    twitter: undefined,
    instagram: undefined,
    facebook: undefined,
  },
	hello() {
		 console.log("Hello, World!");
	}
};

// FUNCI脫N RECURSIVA
function isObject(subject) { // Comprueba si es un objeto
  return typeof subject == "object"; // Devuelve true o false
}

function isArray(subject) { // Comprueba si es una Array
  return Array.isArray(subject); // Devuelve true o false
}

// FUNCI脫N RECURSIVA
// Recibe un parametro que puede ser un objeto, array u otro tipo de dato
function deepCopy(subject) {
  let copySubject; // Esta variable se convertira en array, objeto u otro tipo de dato

  const subjectIsObject = isObject(subject); // 驴El par谩metro es objeto?
  const subjectIsArray = isArray(subject); // 驴El par谩metro es array?

  if (subjectIsArray) { // Si es array...
    copySubject = []; // Asignamos un array vac铆o donde iremos copiando 1 a 1 los datos
  } else if (subjectIsObject) { // Si es un objeto...
    copySubject = {}; // Asignamosun objeto vac铆o donde iremos copiando 1 a 1 los atributos
  } else { // Sino es array u objeto...
    // Entonces es un tipo de dato que se puede copiar sin problemas, retornamos dicho
		// dicho dato y terminamos con la ejecuci贸n de la fucnci贸n.
		return subject;
  }
	
	// Continuamos con la ejecuci贸n de la funci贸n si el par谩metro fue array u objeto: 
  for (key in subject) { // Recorremos cada uno de los atributos o datos del objeto o array
		// Comprueba si hay un objeto dentro del 铆ndice o atributo:
    const keyIsObject = isObject(subject[key]);

    if (keyIsObject) { // Si es verdad que hay un objeto dentro...
	      // Invocamos recursivamente la misma funci贸n:
				copySubject[key] = deepCopy(subject[key]); // 馃憖馃攧
    } else { // Sino...
      if (subjectIsArray) { // Si el par谩metro recibido por la funci贸n deepCopy es Array...
	        // Agregamos el elemento a la variable a retornar al final de la funci贸n:
					copySubject.push(subject[key]);
      } else { 
				// sino, significa que es objeto el par谩metro y adem谩s no hay objetos anidados
				// en el elemento actual dentro del recorrido del bucle for, por tanto, asignamos
				// dicho elemento como valor a la propiedad correspondiente:
        copySubject[key] = subject[key];
      }
    }
  }

  return copySubject; // Finalmente retornamos el objeto/array copia
}

Generemos un objeto copia utilizando la funci贸n recursiva e intentemos realizar modificaciones en el objeto copia y original:

// OBJETO COPIA
const juan = deepCopy(studentBase);

// MODIFICACIONES EN EL OBJETO ORIGINAL
studentBase.socialMedia.twitter = "@student_twitter"

// MODIFICACIONES EN EL OBJETO COPIA
juan.socialMedia.instagram = "@juanDC"

// VEAMOS EN CONSOLA LAS DIFERENCIAS DEL OBJETO ORIGINAL Y LA COPIA
console.log(studentBase);
console.log(juan);

/* > Mensaje en consola
{
  name: undefined,
  email: undefined,
  age: undefined,
  approvedCourses: undefined,
  learningPaths: undefined,
  socialMedia: {
    twitter: '@student_twitter', 馃憟馃憟 馃憖
    instagram: undefined,
    facebook: undefined
  },
  hello: [Function: hello] 馃憟馃憟 FUNCI脫N
}
{
  name: undefined,
  email: undefined,
  age: undefined,
  approvedCourses: undefined,
  learningPaths: undefined,
  socialMedia: { 
		twitter: undefined, 
		instagram: '@juanDC', 馃憟馃憟 馃憖
		facebook: undefined 
	},
  hello: [Function: hello] 馃憟馃憟 FUNCI脫N
}
*/

Podemos notar que los cambios en un objeto no afecta en los valores de las propiedades del otro. Logramos crear una copia de un objeto que no est茅 condicionada a que si el objeto original tiene objetos anidados o si tiene m茅todos dentro.

Conozcamos ahora c贸mo emplear la abstracci贸n en JavaScript con simplemente objetos, es decir, sin utilizar clases. 馃馃殌

Contribuci贸n creada por: Mart铆n 脕lvarez (Platzi Contributor)

Aportes 78

Preguntas 15

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

Hola! Les comparto mi aporte de como entendi el codigo paso por paso:

Funcion bucle compleja pero en recursividad.

let array = [1,23,41,52,42,5,656,6,98]
let numeroArray = 0;

let fun = (numerito) => {
    if( numerito < array.length ) {
    let valorArray = array[numerito];
    console.log(valorArray);
    return fun(numerito + 1)
    } else {
        console.log("fin");
    }  
}

let y = fun(numeroArray);

Deep copy.

Utilizaresmos recursividad para crear copia de los objetos y que no se rompan si tenemos objetso dentro de objetos dentro de objetos, o si tenemos metodos dentro de nuestros objetos.

Bien, deep copy en muchos aspectos es un gran algoritmo con manejo de datos, recursividad, etc etc, por lo tanto ire escribiendo fracciones de codigo y explicandolas, y cua do termine de explicar todo, pondre el algoritmo completo.

const obj1 = {
    a: "a",
    b: "b",
    c: {
       d: "d",
       e: "e", 
    },
    editA() {
        this.a = "AAAAA";
    }
}; 
//lo de aca arriba es el objeto a copiar

function isObject(subject) {
    return typeof subject == "object"
}
function esUnArray(subject) {
    return Array.isArray(subject);
}
//estas 2 funciones son funciones de validacion de datos, estan seran llamads y se les pasaran un parametro, la mayoria de datos se puede validar con typeof, ergo, los arrays son los unicos que tienen un metodo espacial = Array.isArray(objetoAsaberSiEsUnArray)

function deepCopy(subject) {
    let copySubject;
//dentro de sta funcion sucedera todo,el copysubject guardara los datos, este esta esperando a saber si los datos son objetos,arrays u otras cosas como strings
    const subjectIsArray = esUnArray(subject);
    const subjectIsObject = isObject(subject);

//con las constantes subjectIsArray,   subjectIsObject trabajere los datos,  estas son las encargadas de llamar a  las funciones que hicimos fuera de la funcion deepCopy.
  

  if(subjectIsArray) {
        copySubject = [];
    } else if(subjectIsObject) {
        copySubject = {};
    } else {
        return subject;
    }

//por ultimo empezamos a trabajar con los datos ya validados, segun el dato que sea correspondiente, trbajaremos objeto,arrays u otros valores.
//2da parte del algoritmo
for(key in subject) {
//Creamos un bucle for, este bucle (a in b)se puede ejecutar en una estructura de datos como arrays, objetos. Este loop signfica que el elemento a pasara por TODA la estructura de datos de b, y claro, dependieno la posicion de a,este tendra el valor de donde este parado encima. ejemplo: 
//let array = [52,42,56];
//for(a in array) {
	//console.log(array[a]);
//}
        const keyIsObject = isObject(subject[key]);
//con keyIsObject VUELVO a validar si los datos DENTRO de la estructura de datos YA VALIDADA son objetos o datos. 

        if(keyIsObject) {
            copySubject[key] = deepCopy(subject[key]);
// si resulta que son objetos, entonces iremos copiando y pegando los datos en copySubject, y estos datos se iran copiando de manera identica y exitosa gracias la recursividad deepCopy(subject[key]);

} else {
            if(subjectIsArray) {
                copySubject.push(subject[key]);
            } else {
                copySubject[key] = subject[key]
            }
        }
    }
 //estos 2 ultimos casos son mas sencillos ya que simplemente se basa en arrays u elementos que no sean ni arrays ni objetos   
 
    return copySubject;
// Y al final de todo, la funcion debe devolver algo,verdad? en este caso, quien es el que almaceno todos los datos de el objeto que copiamos? el copySubject, bien, ese es quien retornamos.
} 

para mi esta es una de las clases que no entiendes por completo pero que con el tiempo estoy seguro lograr comprender. En conclusi贸n me llevo que copiar objetos en Javascript es un poco laborioso.

Hola compa帽eros 馃榾, estuve jugando un poco con el c贸digo de la case para entenderlo mejor, y se puede simplificar de esta forma, mas sencillo de leer:

function deepCopy(subject) {
  let copy;

  if (Array.isArray(subject)) {
    copy = [];
  } else if (typeof subject === "object") {
    copy = {};
  } else {
    return subject;
  }

  for (key in subject) {
    copy[key] = deepCopy(subject[key]);
  }

  return copy;
}

Ahora ustedes se preguntaran:
驴Porque en el ciclo for ya no hay validaciones?, esto es debido a que el valor key dentro del for va a corresponder a dos posibles valores: indices de un array, o keys de objetos, dependiendo que sea subject (un objeto o un array) , y como esta misma sintaxis sirve para objetos y arrays podemos usar la misma linea de c贸digo, teniendo encuenta que ya antes creamos copy con los valores {} o [] dependiendo si subject era un objeto o array

Jugando un poco con el debugger he visto como la variable let copySubject; empieza a obtener sus elementos
Imagen1
la function deepCopy identifica que es un objecto { } .

Imagen2
los dos primeros elementos ingresan normal: copySubject[key] = subject[key]; //{a,b}.

Imagen3
en el elemento c:{} identifica que hay un objeto .

Imagen4
ingresan de forma normal los elementos copySubject[key] = subject[key]; //{d,e}.

Imagen5
es el momento de ingresar la function editA(){} lo detecta como objeto.

Imagen6
con este ultimo paso, copia todo el contenido de la funcion y para a finalizar la function.

Tomando como inspiraci贸n los aportes de @irvingjuarez y @lgfh, les comparto una soluci贸n efectiva y m谩s corta:

.

.

P.D. Dej茅 los statements a la derecha de los if para que no ocupara m谩s l铆neas y la imagen no fuese m谩s larga.

Deep Copy con recursividad

Se dice que el objeto tiene un Deep Copy cuando cada propiedad del objeto apunta a una copia separada, incluso si la propiedad apunta a un objeto (valores de referencia). Se crea una copia separada del objeto de referencia para el objeto de destino. En caso de copia profunda, las propiedades de referencia del objeto de origen y las propiedades de referencia del objeto de destino apuntan a diferentes ubicaciones de memoria.

Resumen de Deep Copy

  • El objeto de destino contiene una copia separada del nombre, la edad y la designaci贸n.
  • Instancias separadas de tipos de valor. Se crea una referencia separada para objetos complejos (鈥渄irecci贸n鈥)

La propiedad 鈥淒irecci贸n鈥 de los objetos de origen y destino apuntan a diferentes ubicaciones de memoria. Si el usuario actualiza la propiedad de la direcci贸n en el objeto de origen, las actualizaciones no se reflejan en el objeto de destino.

var userName = {
  name: "Mayank Gupta",
  age: 30,
  designation: "Developer",
  address: {
    street: "Rohini",
    city: "Delhi"
  }
}

Lectura importante!

Deep and Shallow Copy in JavaScript

C贸digo Clase

const obj1 = {
    a: 'a',
    b: 'b',
    c: {
        d: 'd',
        e: 'e',
    },
    editA() {
        this.a = 'Abcd'
    }
};

function isObject(subject) {
    return typeof subject == "object";
}
function isArray(subject) {
    return Array.isArray(subject);
}

function deepCopy(subject) {
    let copySubject;

    const subjectIsObject = isObject(subject)
    const subjectIsArray = isArray(subject)
 
    // inicializamos la variable copySubject segun su tipo de dato
    if (subjectIsArray) {
        copySubject = [];
    } else if (subjectIsObject) {
        copySubject = {};
    } else {
        return subject;
    }

    // Empieza la recursividad
    for (key in subject) {
        const keyIsObject = isObject(subject[key]); // propiedad de nuestro elemento

        if (keyIsObject) {
            copySubject[key] = deepCopy(subject[key]) // Si la propiedad es un objeto, se vuelve a llamar a deepCopy para volver a hacer las asignaciones por cada una de las propiedades de los objetos.
        } else {
            if (subjectIsArray) {
                copySubject.push(subject[key])
            } else {
                copySubject[key] = subject[key]
            }
        }
    }

    return copySubject;
}

// Pruebas en devTools
// const obj2 = deepCopy(obj1);

// obj1
// obj2

// obj1.a = 'AMORMIO'

// obj2.a = 'Si estoy debajo del vaiv茅n de tus piernas'

// obj1
// obj2

Esta clase me hizo volar la cabeza pero todo totalmente comprensible! El mejor profe!

Me parece que hay un momento en el que la clase se hace confusa y es el momento en que el profe decide en el ciclo For In anidar el if de si subjectIsArray, y ademas de la anidaci贸n, que utilice subjectIsArray como validaci贸n sin pasarle ningun parametro, a mi parecer debi贸 generar un keyIsArray al igual que lo hizo con keyIsObject, y de paso no anidar el if, a que no tiene proposito en si mismo.
les dejo el mismo codigo solo que con unas peque帽as modificaciones a ver que les parece.

const obj1 = {
  a:"b",
  c:"d",
  f:"g",
  capC(prop) {
    this.prop = toUpperCase(this.prop)
  },
  h:"i",
  j:"k",
}

function isObj (elm) {
  return Object.prototype.toString.call(elm) == '[object Object]'
  // return typeof elm == 'object'
}

function isArr (elm) {
  return Array.isArray(elm)
}

function deepCopy (elmToCopy) {
  let copyElm
  
  let itsAnObject = isObj(elmToCopy)
  let itsAnArray = isArr(elmToCopy)
  
  if(itsAnArray)
  {
    copyElm = []
  } 
  else if (itsAnObject)
  {
    copyElm = {}
  } 
  else 
  {
    return elmToCopy
  }
  
  for(subElm in elmToCopy)
  {
    const subElmItsObj = isObj(elmToCopy[subElm])
    const subElmItsArr = isArr (elmToCopy[subElm])
    
    if(subElmItsObj)
    {
      copyElm[subElm] = deepCopy(elmToCopy[subElm])
    } 
    else if (subElmItsArr)
    {
      copyElm.push(elmToCopy[subElm])
    } else {
      copyElm[subElm] = elmToCopy[subElm]
    }
  }
  
  return copyElm
}

let obj2 = deepCopy(obj1)

console.log(obj2)


Aqui hay un error, ya que en la funcion isObject, incluso aunque le pases como argumento un array, te da true. Sin embargo, existe otra forma de validar eso:
.
El funci贸n deber铆a quedar as铆;

function isObject(subject){
  return Object.prototype.toString.call(subject) == "[object Object]";
}

Sabemos si es un array si el string es [object Array]

Una versi贸n acortada y simplificada que estuve probando 馃槢 :

const deepCopy = elem => {
  if(!isObject(elem)) return elem
  
  const copyOfElem = isArray(elem) ? [] : {}
  
  for(key in elem){
    const current = elem[key]
    
    copyOfElem[key] = isObject(current)
    		? deepCopy(current)
    		: current
  }
  
  return copyOfElem
}

El funcionamiento es el mismo, pero utiliza algunos trucos para acortar espacio

  1. Solo verifica si es un objeto porque los arrays tambi茅n son objetos, as铆 que solo puede ser o un objeto o un primitivo
  2. Para inicializar la copia como solo tiene 2 opciones (array u objeto) entonces usa una ternaria
  3. Con el for in ya recorre el array as铆 que solo debe verificar si el elemento es un objeto o agregar el elemento en esa posici贸n

Hice algunas pruebas y funcionan igual, pero a lo mejor se me escapa alg煤n edge case, si lo ven me servir铆a mucho, grax ;D

Tuve que ver el video 3 veces para lograr comprenderlo, pero al fin pude lograrlo, creo que las clases de Juan son de lo mejor y su energ铆a lo es todo 馃槃

Gracias a las nuevas features de JavaScript馃槑, hoy tenemos una nueva funci贸n que nos puede ayudar para aquellos casos en los que se quiera clonar un objecto o arreglo y no nos baste con un shallow copy 馃.

La funci贸n se llama structuredClone, est谩 permite hacer un deep copy basado en un algoritmo del mismo nombre (Structured Clone) de tal forma que sea mucho mas facil para los devs hacer deep copy de sus estructuras de datos 馃槷.

Aqu铆 un ejemplo de uso:

const myDeepCopy = structuredClone(myOriginal);

Sin embargo esto es relativamente nuevo al dia de hoy y tiene ciertas limitaciones (como el caso donde se tengan funciones dentro del objeto), si quieren leer m谩s al respecto les dejo un articulo donde lo explican m谩s a detalle 馃榾.

esta clase si que me mareo tuve que verla varias veces!! es un excelente profe pero este tema me pudo xD a volver a mirar hasta comprender

Holaa, comparto mi solucion a la funcion deepCopy

function typeOfElem(elem) {
  let result;

  switch (Object.prototype.toString.call(elem)) {
    case "[object Object]":
      result = "object";
      break;
    case "[object Array]":
      result = "array";
      break;
    default:
      result = "no problem";
      break;
  }

  return result;
}

function deepCopy(elem) {
  let copy;
  let elemType = typeOfElem(elem);

  if (elemType === "array") {
    copy = [];
  } else if (elemType === "object") {
    copy = {};
  } else {
    return elem;
  }

  for (let item in elem) {
    let elemType2 = typeOfElem(item);

    if (elemType2 === "object") {
      item = deepCopy(item);
    }

    if (elemType === "array") {
      copy.push(item);
    } else {
      copy[item] = elem[item];
    }
  }

  return copy;
}

Maneras de copiar un Array(Deep and shallow)

Existen diferentes maneras de copiar un array, una de ellas es con el m茅todo slice(), que nos permite copiar un array sin modificar el original.

var original = [true, true, undefined, false, null];

//slice()
var copy1 = original.slice(0);

//spread operator
var copy2 = [...original];

Estas tienden a no funcionar cuando hay un objeto o un arreglo dentro de un array. Cuando pasa eso necesitas un deep copy
shallow copy:

var deepArray = [["Carlos"]];
var shallowCopy = deepArray.slice(0);

shallowCopy[0].push("es chevere");
console.log(deepArray[0], shallowCopy[0]);
// ["Carlos", "es chevere"]


var deepCopy = JSON.parse(JSON.stringify(deepArray));
deepCopy[0].push("es chevere");
console.log(deepArray[0],deepCopy[0])


Cuando hacemos copy, copiamos el pointer del original array

Nunca me imagine que copiar un Objeto fuese de esta manera tan compleja

Me perd铆 entre tantos objetos 馃槮

Ac谩 esta mi aporte, utilice algunas especificaciones de ES6+
Pueden ver el resto de los retos que he resuelto en este y otros cursos de esta misma escuela ac谩: https://github.com/EdinsonRequena/JsSchool
Espero les sirva de ayuda 鉂わ笍

const isObject = subject => typeof subject == 'object'
const isArrayFunc = subject => Array.isArray(subject)

const deepCopy = subject => {
    let copySubject

    const subjectIsObject = isObject(subject)
    const subjectIsArray = isArrayFunc(subject)

    if (subjectIsArray) copySubject = []
    else if (subjectIsObject) copySubject = {}
    else subject

    for (let key in subject) {
        const keyIsObject = isObject(subject[key])
        if (keyIsObject) copySubject[key] = deepCopy(subject[key])
        else subjectIsArray ? copySubject.push(subject[key]) : copySubject[key] = subject[key]
    }

    return copySubject
}

const obj = {
    name: 'Andrea',
    lastName: 'Vinas',
    email: 'andre',
    age: 21,
    objectTest: {
        a: 'a',
        b: 'b',
        1: '1',
    },
    aprovedCourse: ['JavaScript', 'NodeJS', 'ReactJS'],
    addCourse(newCourse) {
        this.aprovedCourse.push(newCourse);
    }
}

const example = deepCopy(obj)

As铆 fu como lo entend铆

//DEEP COPY


    //Funciones para comprobar que el tipo de dato

function isObject(subject){
    return typeof subject == "object"; // recordar que los arrays tambien son de tipo objeto en js
}

function isArray(subject) {
    return Array.isArray(subject);
}

    // Empieza la funcion de copiado profundo

Empieza la funcion de copiado profundo

function deepCopy(subject) {
    let copySubject; // Inicializa la constante que enviara al final

comprueba que la variable enviada sea un array o un objeto

    const subjectIsObject = isObject(subject); // si es array u objeto va a dar true

    const subjectIsArray = isArray(subject); // s贸lo si es array dara un true

Es necesario que este ciclo if compruebe primero que es un array, ya que como se vio anteriormente los array tambi茅n son objetos

    if (subjectIsArray) {
        copySubject = []; // transforma la variable inicializada en un array
        console.log("Es array");
    } else if (subjectIsObject) {
        copySubject = {}; // transforma la variable inicializada en un objeto
        console.log("Es objeto");
    } else {
        return subject;
 // en caso de que no sea una variable tipo objeto termina la funcion enviando solo el dato a copia
    }

    for (key in subject) {
        const keyIsObject = isObject(subject[key]); // Comprueba que la Key sea un variable de tipo objeto
        if (keyIsObject) {
            copySubject[key] = deepCopy(subject[key]); // En caso que lo sea llamara la funcion deepCopy de nuevo
        } else {
            if (subjectIsArray) {
                copySubject.push(subject[key]); // Se envia el valor de la Key que no es de tipo objeto (Number, String o boolean) al array copiado
            } else {
                copySubject[key] = subject[key]; // Se evia copia de la key al objeto copiado
            }
        }
    }
    return copySubject;};

`

Les comparto como anot茅 lo que hace la funci贸n deepCopy para mis apuntes:

  1. Recibe como par谩metro una variable.
  2. Se verifica si es un objeto, array o otro tipo de variable.
    1. Si es objeto o array entra en un ciclo. Sino retorna la copia de la variable.
  3. Si se entra al ciclo, por cada elemento o atributo del objeto o array
    1. Se verifica nuevamente si es objeto, array o variable.
      1. Si este atributo es un objeto, se llama de nuevo a la misma funci贸n. (Ac谩 esta la recursividad). Y se vuelve al primer paso hasta copiar este objeto.
    2. Si es un array se utiliza el m茅todo push.
    3. Si es otro tipo de variable solo se hace una asignaci贸n normal.
  4. Finalmente el ciclo acaba y se devuelve el array o el objeto copiado.

Deep copy con recursividad

const obj1 = {
  a: 'a',
  b: 'b',
  c: {
    d: 'd',
    e: 'e',
  },
  editA() {
    this.a = 'AAAAA';
  }
};

function isObject(subject) {
  return typeof subject === 'object' && subject !== null;
}

function isArray(subject) {
  return Array.isArray(subject);
}

function deepCopy(subject) {
  let copySubject;

  const subjectIsArray = isArray(subject);
  const subjectIsObject = isObject(subject);

  if (subjectIsArray) {
    copySubject = [];
  } else if (subjectIsObject) {
    copySubject = {};
  } else {
    return subject;
  }

  for(key in subject) {
    const keyIsObject = isObject(subject[key]);

    //*if else - if else
    keyIsObject ? copySubject[key] = deepCopy(subject[key]) : subjectIsArray ? copySubject.push(subject[key]) : copySubject[key] = subject[key];
  }

  return copySubject;
}

deepCopy(obj1);

Excelente clase, cada detalle bien llevado hasta aqui.

// Esta funci贸n comprueba si un objeto es v谩lido (no nulo) y es un objeto.
function isObject(obj) {
  return obj !== null && typeof obj === "object";
}

// Esta funci贸n comprueba si una variable es un array.
function isArray(arr) {
  return Array.isArray(arr);
}

// Esta es la funci贸n principal que se encarga de hacer una copia profunda de un objeto o array.
function deepCopy(subject) {
  // Primero, comprobamos si el sujeto es un objeto o array v谩lido.
  if (isObject(subject)) {
    // Si es un array, creamos una copia vac铆a.
    // Si no, creamos un objeto vac铆o.
    const copySubject = isArray(subject) ? [] : {};

    // Usamos Object.entries() para obtener tanto la clave como el valor de cada propiedad.
    for (const [key, value] of Object.entries(subject)) {
      // Comprobamos si el valor de la propiedad es un objeto o un array.
      if (isObject(value)) {
        // Si es un objeto o un array, llamamos a deepCopy() de forma recursiva para copiarlo.
        // Luego asignamos la copia al objeto o array nuevo.
        copySubject[key] = deepCopy(value);
      } else {
        // Si no es un objeto o un array, simplemente copiamos el valor al objeto o array nuevo.
        copySubject[key] = value;
      }
    }

    // Devolvemos el objeto o array nuevo con todas las propiedades copiadas.
    return copySubject;
  } else {
    // Si no es un objeto o array v谩lido, simplemente devolvemos el valor original.
    return subject;
  }
}

En resumen, la funci贸n deepCopy realiza una copia profunda de un objeto o array en JavaScript. Primero comprueba si el sujeto es un objeto o array v谩lido. Si es v谩lido, crea un nuevo objeto o array vac铆o y utiliza un bucle for鈥f para recorrer todas las propiedades del objeto o array original. Para cada propiedad, comprueba si su valor es un objeto o array. Si lo es, llama a deepCopy de forma recursiva para copiarlo y asigna la copia al objeto o array nuevo. Si no lo es, simplemente copia el valor al objeto o array nuevo. Finalmente, devuelve el objeto o array nuevo con todas las propiedades copiadas. Si el sujeto no es un objeto o array v谩lido, simplemente devuelve el valor original.

Me queda una duda en este punto.
Los arrays dentro de JavaScript tambi茅n son Objetos, por lo tanto, la validaci贸n dentro de la funci贸n isObject, tambi茅n va a retornar true cuando sele pase un array. En consecuencia, se podr铆a ejecutar el if y el else if en el condicional. Debido a que no. La est谩n mandando a salir del condicional cuando es un array.

Hola a todos, les comparto mi c贸digo de deep copy.

El c贸digo copia todo hasta la capa m谩s profunda, vi que el c贸digo de la clase no llega tan profundo, as铆 que le mejor茅 esa parte.

Les dejo un sreenshot del c贸digo y el c贸digo como tal.
Todo feedback es bienvenido. 馃槃

function isObjectOrArray (element) {
	const ELEMENT_IS = {
		'[object Object]' : 'object',
		'[object Array]'  : 'array'
	};
	const TYPE_ELEMENT = Object.prototype.toString.call(element);
	const IS_ELEMENT_ANY = TYPE_ELEMENT !== '[object Object]' && TYPE_ELEMENT !== '[object Array]';
	const RESULT = (IS_ELEMENT_ANY)
		? 'any'
		: ELEMENT_IS[TYPE_ELEMENT];

	return RESULT;
}

function deepCopy (subject) {
	const SUBJECT_IS = isObjectOrArray(subject);

	if (SUBJECT_IS === 'any')
		return subject;
	const COPY_SUBJECT = (SUBJECT_IS === 'array')
		? []
		: {};

	for (const KEY in subject) {
		const IS_KEY_ANY = isObjectOrArray(subject[KEY]) === 'any';

		COPY_SUBJECT[KEY] = (IS_KEY_ANY)
			? subject[KEY]
			: deepCopy(subject[KEY]);
	}

	return COPY_SUBJECT;
}

Esta clase si me exploto la cabeza JAJA.
Pero nada que no sea entendible, solamente es de repasarlo y practicar!

Una parte de mi se emociona por el desafio que representaria usar una funcion recursiva sin generar un 鈥淪tack Overflow鈥.
Adem谩s, pienso que al momento de implementar dicha funcionalidad el c贸digo ser铆a m谩s escalable. En cuanto a proyectos grandes.

Toda la clase o el tema estuvo muuuy loco y me volo la cabeza una parte en especial.
este fue mi objeto de prueba:

const obj1 = {
  a: "a",
  b: "b",
  c: {
    d: "d",
    e: "e"
  },
  f: ["鈾戯笍", "馃拃", "鈽笍", "馃捇"],
  g: () => {
    console.log("hi i'm a method in 'g'");
  },
  h: [1,2,3,{cuatro: '4', editA: () =>{this.a = 'AAAAA'}}]
};

Como pueden ver tiene arrays dentro de sus propiedades y a la vez arrays con objetos como elementos.
Mi problema principalmente era que no entend铆a c贸mo validamos que una de las propiedades fuera un array, si solamente estamos validando con isObject(subject[prop]) y no con isArray鈥 Luego todo cobro sentido cuando recorde que un array (as铆 como muchas cosas en JS) es un objeto:

Noten que las dos validaciones de isArray e isObject son true en mi subject que es un array dentro de mi objeto. Asi que un Array([ ]) es un Array(obviamente) y es un objeto(al menos en nuestra validaci贸n con typeof , pero un objeto ({ })es un objeto(obviamente) y no es un array.

Bueno al menos esto fue lo que deduje y entend铆, si estoy equivocado en mi razonamiento diganme para no vivir enga帽ado otra vez XD.

La mejor forma para entender esta clase es usando debugger en el navegador es lo m谩ximo

Est谩 muy buena la clase y m谩s que todo para hacer el ejercicio 馃憦, pero hoy en d铆a ya tenemos una forma nativa de como hacer copias profundas en JS.

Por si no lo conoc铆an se llama structureClone aqu铆 les paso la doc por si la necesitan. https://developer.mozilla.org/en-US/docs/Web/API/structuredClone

Pero ojo con el soporte para navegadores antiguos
https://caniuse.com/?search=structuredClone

Una Deep Copy establece una copia de los elementos que forman parte del objeto, pero omitiendo la copia de sus referencias. Es decir, creando un nuevo objeto en memoria, copiando o clonando su original, lo que representa un snapshoot del objeto en s铆 mismo en un momento dado.

Hola!!, llegue un a帽o tarde, pero este seria una propuesta para lo hecho, no se que tan bien esta, pero lo interesante es que funciona

const obj1 = {
    a: 'a',
    b: 'b',
    c: {
        d: 'd',
        e: 'e'
    },
    editA() {
        this.a = 'AAAA'
    }
}

const elements = {
    "[Object Object]": {},
    "[Object Array]": []
}

function typeOfElement(subject) {return Object.prototype.toString.call(subject)}

function deepCopy(subject){
    let copySubject;
    
    const subjectIsAnElement = typeOfElement(subject);
    
    copySubject = elements[subjectIsAnElement] || subject
    
    for(let key in subject){
        const keyIsElement = typeOfElement(subject[key]);
        
        if(keyIsElement.includes('Object')) copySubject[key] = deepCopy(subject[key])

        keyIsElement.includes('Array') 
        ? copySubject.push(subject[key]) 
        : copySubject[key] = subject[key]
    }
    return copySubject;
}

deep copy copiado de objetos sin errores

Cabe destacar algo aqu铆 y es que chequear tipos con typeof no es la mejor manera de hacer las cosas en JS.
.
Recordemos que en Javascript todo es un objeto y a veces un typeof === 'object' puede no ser todo lo confiable que esperar铆as, por ejemplo:

typeof null === 'object' // true
typeof [] === 'object' // true

Hay muchos casos en donde este tipo de comprobaciones no son de fiar, es preferible muchas veces ingeniarselas un poquito y pensar m谩s all谩鈥 por ejemplo 驴Que es lo que todo objeto literal tiene? Pues, keys. Entonces:

if (Object.keys(subjectIsObject).length) {
  ...
}

Lo anterior ser铆a una soluci贸n b谩sicamente infalible, si el item devuelve un array, entonces ya sabes que es un literal.

Este ser铆a un buen ejercicio de leetcode 馃槂

Costo un poco pero al final sali贸, ac谩 dejo una soluci贸n
que hice antes de ver la clase como reto!

function recursiveCopy (src,target){    
  
    for(props in src){
        let aux;
        if( isObject(src[props]) && !isArray(src[props])){
            aux = props;
            target[aux] = {};
            recursiveCopy(src[props], target[aux]);
        }else if(isArray(src[props])){
            aux = props;
            target[aux] = [];
            for(index of src[aux]){
                recursiveCopy(src[props],target[aux]);
            }
        }else{
            target[props] = src[props] 
        }       
    }
}

function isObject(prop){    
    return typeof prop === "object";
}

function isArray(prop){
    return Array.isArray(prop);
}
//esto es declarar la variable
let copySubject;

//Esto es inicializarla
copySubject = "cualquierValor";

Tuve que releer el c贸digo del bucle un par de veces, pero finalmente logr茅 entenderlo 馃槃

Tenia la duda si dentro del obj1 hay un Array, y luego de hacer el const obj2 = deepCopy(obj1), trato de modificar el Array del obj1 agregando con push un valor, al probar en console, no se va a modificar el obj2 En Resumen: funciona tambien si dentro de mi objeto tengo Arrays

Aqui dejo mi versi贸n refactorizada de deepCopy:

function deepCopy(subject) {
  if (typeof subject !== 'object') return subject;
  const copySubject = Array.isArray(subject) ? [] : {};
  Object.keys(subject).forEach(key => {
    copySubject[key] = deepCopy(subject[key]);
  })
  return copySubject;
}

me hizo recordar cuando en la universidad nos pidieron elaborar un programa que le pegaras un bloque de codigo y te dijera que lenguaje era cuantas variables se habian creado y si existian condicionales y cuantos eran鈥 analizar linea por linea los texto, en este caso analizando cada loop del for in

Debugeado a mano para quienes no sepan que esta pasando a la perfeccion 鉂わ笍

function deepCopy(subject) {
    let copySubject;

    const subjectIsObject = isObject(subject);
    const subjectIsArray = isArray(subject);

    if (subjectIsArray) 
    {
        copySubject = [];
        console.log("Inicializammos en ", copySubject);
    } 
    
    else if (subjectIsObject) 
    {
        copySubject = {};
        console.log("Inicializamos en ", copySubject);
    } 
    else 
    {
        return subject;
    }

    for (key in subject) 
    {
        const keyIsObject = isObject(subject[key]);

        if (keyIsObject) 
        {
            copySubject[key] = deepCopy(subject[key]);
            console.log(copySubject, "BandObject");
        } 
        
        else 
        {
            if (subjectIsArray) 
            {
                copySubject.push(subject[key]);
                console.log(`push of ${subject[key]} : BandArray`);
            } 

            else 
            {
                copySubject[key] = subject[key];
                console.log(copySubject, " BandNormie");
            }
        }
    }

    return copySubject;
}

Si ven algun error agradezco de sus comentarios

Simplific谩ndolo un poco, el c贸digo quedar铆a as铆:

function deepCopy(element) {
  let copy;
  
  if (Array.isArray(element)) copy = [];
  else if (typeof element === "object") copy = {};
  else return element;
  
  for (item in element) {
    copy[item] = deepCopy(element[item]); 
  }
  return copy;
}

En ese caso yo lo hago asi鈥 estoy en el 2030

//objeto ejemplo
const original= {
    name: "Pedrito",
    lastName: "Roca",
    personalinformation: {
       date: "11-11-2222",
       phone: 1122334455, 
    },
    editA() {
        this.name = "Pietro";
    },
    unascosas:[1,2,3,{a:"holaa", b:"lalalsl", c:23},5,6]
}; 

//metodo ultrasuperfantastico para copiar
const copia = {...original};

console.log(original);
console.log(copia);

Mi propuesta del algoritmo

function miDeepCopy(subject){
    let copySubject;
    if (typeof subject === 'object' && subject !== null) {
        copySubject = {};
    } else if(Array.isArray(subject)){
        copySubject = [];
    }else{
        return subject;
    }

    for(let i in subject){
        if(typeof subject[i] === 'object' && subject[i] !== null){
            copySubject[i] = miDeepCopy(subject[i]);
        }else if(Array.isArray(subject[i])){ //if it is an array
            copySubject[i] = subject[i].slice();
        }else{
            copySubject[i] = subject[i];
        }
    }
    return copySubject;
}

me siento satisfecho de aprender a la primera esto, puedo mimir en paz hoy

a pesar que tuve que repetir la clase un par de veces, y detenerme en la explicacion y reflexionar lo que decia el profe, es gratificante poder entender el codigo, y asi mejorar nuestra comunicacion con nuestra maquina, muy satisfecho con esta clase.


//Original object
const obj1 = {
    a: "a",
    b: "b",
    c: {
        d: "d",
        e: "e",
    },
    // f: ["apple", "banana"],
    editA() {
        this.a = "aaaa";
    }
};

//----------- Recursion. Recursive function

//Validators
function isObject(subject) {
    return typeof subject == "object";
}

function isArray(subject) {
    return Array.isArray(subject);
}

//DeepCopy function
function deepCopy(subject) {
    let copySubject;

    //Validator inside the function
    const subjectIsObject = isObject(subject);
    const subjectIsArray = isArray(subject);

    //Initialize the variable copySubject 
    if(subjectIsObject) {
        copySubject = {};
    } else if (subjectIsArray) {
        copySubject = [];
    } else {
        return subject;
    }

    //For loop
    for (key in subject) {
        //Check if the key is an object
        const keyObject = isObject(subject[key]);
        const keyArray = isArray(subject[key]);
        //Make conditionals. Object, array, something else.
        if(keyObject) {
            copySubject[key] = deepCopy(subject[key]);
        } else {
            if(keyArray) {
                copySubject.push(subject[key]);
            } else {
                copySubject[key] = subject[key];
            }
        }
    }
    return copySubject;
}

Algo curioso que note jugando con la funcion 鈥榠sObject鈥 es que devuelve 鈥榯rue鈥 con los arrays tambien, incluso haciendo mas estricta la comparacion con ===

function isObject(subject) {
  return typeof(subject) == 'object';
}
const object = {};
const array = [];

console.log(isObject(array))  // true

Esta clase podr铆a llegar a ser un poco confusa si no se tienen bien los fundamentos, b谩sicamente estamos reduciendo los objetos a datos primitivos los cuales guardan el valor y no la referencia en memoria, por lo cual al copiarlos estamos copiando el valor que tienen guardado.

Yo simplemente hubiese usado el desestructurador de objetos y sha, jaja

Pero entiendo que la recursividad era par dar un ejemplo de su uso

const obj1 = {
  a: "a",
  b: "b",
  c: {
     d: "d",
     e: "e", 
  },
  editA() {
      this.a = "AAAAA";
  }
};
function isArray (subject) { return Array.isArray(subject) };
function isObject (subject) { return typeof subject == "object" };

function deepCopy(subject) {
  let copySubject;
  const subjectIsArray = isArray(subject);
  const subjectIsObject = isObject(subject);

  if(subjectIsArray) copySubject = [];
  else if(subjectIsObject) copySubject = {};
  else return subject;

  for( key in subject ) {
    const keyIsObject = isObject(subject[key]);
    if(keyIsObject) {
      copySubject[key] = deepCopy(subject[key]);
    } else {
      if(subjectIsArray) {
        copySubject.push(subject[key]);
      } else {
        copySubject[key] = subject[key];
      }
    }
  }

  return copySubject;
}  

Les dejo mis apuntes de la clase donde tambien revisar mis apuntes del curso en gitbook:
teniendo como base el siguiente objeto con metodos vamosa ir aplicando la recursividad con el deep Copy:

const obj1 = {    a: "a",    b: "b",    c: {        d: "d",        e: "e",    },    editA() {        this.a = "AAAAAA";    }};

Validaremos si nuestro objeto de prueba es un objeto o si es un array, en el uno utilizaremos la palabra reservada typeof que nos permite validar si nuesto objetodePrueba es un objeto o lo que le pidamos, y con el array llamamos al superprototypoArray y luego a su metodo estatico isArray.

function isObject(subject) {    return typeof subject == "object";}
function isArray(subject) {    return Array.isArray(subject);}

Para hacer el deepcopy vamos a validar si es un objeto o un array y de acuerdo a eso validaremos y daremos una respuesta de copiado seg煤n sea un objeto o un array

function deepCopy(subject) {    
	let copySubject;
        const subjectIsObject = isObject(subject);
	const subjectIsArray = isArray(subject);
        if (subjectIsArray) {
        copySubject = [];
	} else if (subjectIsObject) {        
	copySubject = {};
    	} else {
        return subject;
    }        for (key in subject) {
        const keyIsObject = isObject(subject[key]);
        if (keyIsObject) {
            copySubject[key] = deepCopy(subject[key])
        } else {
            if (keyIsObject) { 
                 copySubject[key] = deepCopy(subject[key]);
	} else {
                if (subjectIsArray) {
                    copySubject.push(subject[key]);
                } else {
                    copySubject[key] = subject[key];
                }
            }
        }
    }        return copySubject;
}

De esta forma iteramos la copia de nuestros objetos por cada uno de sus valores, ya tengan otros objetos u otros arrays dentro de ellos, incluyendo a sus m茅todos.

Excelente clase 馃榾

.

Me parece que JavaScript acaba de implementar un m茅todo para hacer un deep copy de un objeto: structuredClone.

https://developer.mozilla.org/en-US/docs/Web/API/structuredClone

Hola, esta es mi versi贸n del deepcopy, espero les guste y puedan ahcer correcciones al c贸digo

const obj1 = {
  a: {
    a1: "a",
    a2: "a",
  },
  b: "b",
  edita() {
    this.a.a1 = "aaaaaa";
  },
};

let obj2 = {};

const isObject = (intro) => {
  return typeof intro === "object" ? true : false;
};

const isArray = (intro) => Array.isArray(intro);

const deepCopy = function (objecToCopy, pasteIn) {
  if (isObject(objecToCopy)) {
    pasteIn = {};
  } else if (isArray(objecToCopy)) {
    pasteIn = [];
  } else {
    return objecToCopy;
  }

  for (let item in objecToCopy) {
    if (isObject(objecToCopy[item])) {
      pasteIn[item] = deepCopy(objecToCopy[item], pasteIn[item]);
    } else if (isArray(objecToCopy[item])) {
      pasteIn.push(objecToCopy[item]);
    } else {
      pasteIn[item] = objecToCopy[item];
    }
  }
  return pasteIn;
};

console.log(deepCopy(obj1, obj2));

Muy complicado no entend铆 nada.

Creo que lo que hace confuso la clase es que es muy teorico, y no vemos un resultado hasta el final. Entre toda la explicacion y lineas nos perdemos, son 14 minutos seguidos de codigo sin ver resultado.

Esta clase es la clase para ver varias veces, leer todos los comentarios, leer las preguntas y respuestas y aun as铆 tener la sensaci贸n que algo falta como un vac铆o que no se comprende.
Buena clase

juan ayuda!

Creo que encontr茅 un problema con la funcion deepCopy

function deepCopy(subject) {
  let copySubject;

  const subjectIsObject = isObject(subject);
  const subjectIsArray = isArray(subject);

  if (subjectIsArray) {
    copySubject = [];
  } else if (subjectIsObject) {
    copySubject = {};
  } else {
    return subject;
  }

  for (let key in subject) {
    const keyIsObject = isObject(subject[key]);

    if (keyIsObject) {
      copySubject[key] = deepCopy(subject[key]);
    } else {
      if (subjectIsArray) {
        copySubject.push(subject[key]);
      } else {
        copySubject[key] = subject[key];
      }
    }
  }

  return copySubject;
}```

Este es el codigo que se hizo en la clase ^


Quiero resaltar que durante la siguiente validaci贸n tenemos un problema de logica

for (let key in subject) {
const keyIsObject = isObject(subject[key]);

if (keyIsObject) {
  copySubject[key] = deepCopy(subject[key]);
} else {
  if (subjectIsArray) {
    copySubject.push(subject[key]);
  } else {
    copySubject[key] = subject[key];
  }
}

}```

Si se dan cuenta cada vez que se ejecute este codigo

if (keyIsObject) {
      copySubject[key] = deepCopy(subject[key]);
    } else {
      if (subjectIsArray) {
        copySubject.push(subject[key]);
      } else {
        copySubject[key] = subject[key];
      }

Siempre tendremos como resultado que el key que estemos evaluando sera un instanceof object, la razon es porque los arrays son instacias del prototipo object, entonces la validacion
" if (subjectIsArray)" nunca sera realmente util

me di cuenta de este problem comprobando la efectividad de copiar arrays con metodos como push, el caso es que si la validacion " if (subjectIsArray)" funcionara probablemente la funcion deepCopy estaria rota, porque solo haria una shallow copy de los arrays, la razon por la que funciona correctamente en este momento es porque se aplica la recursividad cuando se valida si es un instanceof object con el metodo isObject cuyo return instanciamos en keyIsObject

en resumen, el codigo funciona bien pero hay un error y si no us谩ramos las validaciones correctas terminar铆amos con shallow copies de los arrays

bajo el mismo contexto, no es necesario que mantengamos esa validaci贸n, si lo removemos del codigo igual funciona bien

ejemplo :

function deepCopy(subject) {
  let copySubject;

  const subjectIsObject = isObject(subject);
  const subjectIsArray = isArray(subject);

  if (subjectIsArray) {
    copySubject = [];
  } else if (subjectIsObject) {
    copySubject = {};
  } else {
    return subject;
  }

  for (let key in subject) {
    const keyIsObject = isObject(subject[key]);

    if (keyIsObject) {
      copySubject[key] = deepCopy(subject[key]);
    } else {
      copySubject[key] = subject[key];
    }
  }

  return copySubject;
}```



<code>



Si les cuesta entenderlo hagan la l贸gica en una libreta con pseudoc贸digo o diagrama, vean el video y repl铆quenlo en la libreta sin ver el c贸digo de Juan al inicio cuesta pero les asegura que se si le dedican tiempo y paciencia terminaran haciendo hasta su propia soluci贸n.

hoy siento que no podr铆a hacer esto solo ni de broma, pero espero volver a ver este comentario en un tiempo m谩s y reirme de m铆 mismo.

No entend铆 ni 馃惀. Me toca volver a ver la clase.

Me cuesta entender la recursividad ya que es un concepto realmente dif铆cil de comprender por esta raz贸n estuve realizando b煤squedas para de como funciona y encontr茅 este video que me ayudo a comprender un poco mas la recursividad, pero espero en mi futuro tener mas claro este concepto para saber cuando es una buena opci贸n usarlo.

Hay un bug en la funcion isObject, la comparacion devuelve true cuando el argumento es un objeto, pero cuando el argumento es un array devuelve tambien true 馃榾

No hay caso. No puedo hacer que funcione. Al modificar un objeto se modifica tambi茅n el otro, incluso copiando el codigo que est谩 en recursos.

Hola!! encontre un peque帽o problema, ahora vere como resolverlo pero queria comentarlo aca para ver las soluciones que implementaron, Cuando ejecuto la funci贸n isObject

function isObject(subject) {
  return typeof subject == "object";
}

Y pas贸 un array ejemplo let a = [1,2,5,7,89,23]; , esta tambien me retorna que es true!

Muchachos ya hay una manera mas f谩cil de copiar obj, sin la referencia en memoria, sino creando un nuevo obj.
Esto sin hacer todo lo que el profe dijo:

const obj1 = {
    a: 'a',
    b: {
        c: 'c',
        d: 'd'
    },
    saludar(){
        return this.a
    }
}

//Spreed Operator
const obj2 = {...obj1} ;

obj2.a = 'Este es obj2'

console.log('obj1', obj1)
console.log('obj2', obj2)
console.log(obj2.saludar());

Exelente clase, qued贸 mucho m谩s claro el concepto introducido en la clase anterior.

UIff!! como el nombre de la clase mismo lo dice, vaya que esto si estuvo profundo y enredado de entender, como al minuto 6" ya me perd铆馃檪馃槬

Estuve buscando en que momento se usaba el spread operator, asi que el spread operator seria un deep copy,

rayos, el profe siempre se equivoca con lo de declarar e inicializar xD

esta clase ha sido bien compleja鈥

que buena clase, es complejho pero est谩 muy bien explicado y se hace m谩s f谩cil. Encontr茅 un peque帽o error: la funci贸n isObject devuelve true cuando le pasamos un array. Lo solucion茅 para la funci贸n deepCopy cambiando un poco la valdiaci贸n:

function deepCopy (subject) {
    let copySubject;
    if (isObject(subject) && !isArray(subject)) { //si no es un array pero si es un objeto
        copySubject = {};
        for (key in subject) {
           copySubject[key] = deepCopy(subject[key]) 
        }
    } else if (isArray(subject)) {
        copySubject = [];
        for (key in subject) {
            copySubject.push(subject[key]);
        }
    } else {
        copySubject = subject
    }
    return copySubject
}

Seguro hay mejores maneras de hacerlo, espero que a alguien le sirva igual