Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Shallow copy en JavaScript

6/19
Recursos

Aportes 24

Preguntas 6

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

Shallow Copy se refiere a la forma de crear un nuevo objeto a partir de las propiedades de otro. Esta copia solo se hace a un nivel alto, no se hace con objetos dentro de objetos (nested objects), lo que provoca que la modificación de una de sus propiedades, modifique el objeto principal.

const person = {
	name: 'Eduardo',
	email: '[email protected]',
  social: {
    facebook: 'Eduardo Garcia',
    twiiter: 'EduGar'
  }
}

const person2 = {}

for (prop in person) {
  person2[prop] = person[prop]
}

person2.name = 'Eduardo Miguel'
person
/* {
  name: 'Eduardo',
  email: '[email protected]',
  social: { facebook: 'Eduardo Garcia', twiiter: 'EduGar' }
} */

person2
/* {
  name: 'Eduardo Miguel',
  email: '[email protected]',
  social: { facebook: 'Eduardo Garcia', twiiter: 'EduGar' }
} */

person2.social.facebook = 'Eduardo Miguel Garcia'
person
/* {
  name: 'Eduardo',
  email: '[email protected]',
  social: { facebook: 'Eduardo Miguel Garcia', twiiter: 'EduGar' }
} */

person2
/* {
  name: 'Eduardo Miguel',
  email: '[email protected]',
  social: { facebook: 'Eduardo Miguel Garcia', twiiter: 'EduGar' }
} */

Existe un método del objeto Object que nos permite hacer esta copia directa, con el método Object.assign(). Sin embargo, este método sigue conservando el problema de los objetos internos.

const person = {
	name: 'Eduardo',
	email: '[email protected]',
  social: {
    facebook: 'Eduardo Garcia',
    twiiter: 'EduGar'
  }
}

const person2 = Object.assign({}, person)

person2.name = 'Eduardo Miguel'
person
/* {
  name: 'Eduardo',
  email: '[email protected]',
  social: { facebook: 'Eduardo Garcia', twiiter: 'EduGar' }
} */

person2
/* {
  name: 'Eduardo Miguel',
  email: '[email protected]',
  social: { facebook: 'Eduardo Garcia', twiiter: 'EduGar' }
} */

person2.social.facebook = 'Eduardo Miguel Garcia'
person
/* {
  name: 'Eduardo',
  email: '[email protected]',
  social: { facebook: 'Eduardo Miguel Garcia', twiiter: 'EduGar' }
} */

person2
/* {
  name: 'Eduardo Miguel',
  email: '[email protected]',
  social: { facebook: 'Eduardo Miguel Garcia', twiiter: 'EduGar' }
} */

De la misma manera existe otro método que nos permite hacer esta copia, el método Object.create(). A diferencia de los métodos anteriores, este método copia un objeto como el prototipo del nuevo objeto. Sin embargo, sigue conservando el mismo problema de los objetos internos.

const person = {
	name: 'Eduardo',
	email: '[email protected]',
  social: {
    facebook: 'Eduardo Garcia',
    twiiter: 'EduGar'
  }
}

const person2 = Object.create(person)

person2.name = 'Eduardo Miguel'
person
/* {
  name: 'Eduardo',
  email: '[email protected]',
  social: { facebook: 'Eduardo Garcia', twiiter: 'EduGar' }
} */

person2
/* {
  name: 'Eduardo Miguel',
  __proto__: {
    name: 'Eduardo Miguel',
    email: '[email protected]',
    social: {
      facebook: 'Eduardo Garcia',
      twiiter: 'EduGar'
    }
  }
} */

person2.social.facebook = 'Eduardo Miguel Garcia'
person
/* {
  name: 'Eduardo',
  email: '[email protected]',
  social: { facebook: 'Eduardo Miguel Garcia', twiiter: 'EduGar' }
} */

person2
/* {
  name: 'Eduardo Miguel',
  __proto__: {
    name: 'Eduardo Miguel',
    email: '[email protected]',
    social: {
      facebook: 'Eduardo Miguel Garcia',
      twiiter: 'EduGar'
    }
  }
} */

Shallow copy en JavaScript

Shallow copy

El Shallow Copy (copia superficial) es una copia bit a bit de un objeto. Se crea un nuevo objeto que tiene una copia exacta de los valores del objeto original. Si alguno de los campos del objeto son referencias a otros objetos, solo se copian las direcciones de referencia, es decir, solo se copia la dirección de memoria.

Object.assign()

El método Object.assign () copia todas las propiedades propias enumerables de uno o más objetos de origen a un objeto de destino. Devuelve el objeto de destino modificado.

Las propiedades del objeto de destino se sobrescriben con las propiedades de los orígenes si tienen la misma clave. Las propiedades de las fuentes posteriores sobrescriben a las anteriores.

Object.create()

El método Object.create () crea un nuevo objeto, utilizando un objeto existente como prototipo del objeto recién creado.

La diferencia entre Object.create y Object.assign

La principal diferencia entre Object.create() y Object.assign() es que el método Object.assign crea un nuevo Object. utiliza el objeto proporcionado como prototipo del Objeto recién creado. Mientras que el método Object.assign() copia todas las propiedades de los objetos de origen al objeto de destino, que es el primer parámetro de esta función y devuelve este Objeto de destino.

Por lo tanto, vemos que mientras Object.create() define propiedades en nuestro Object recién creado. Object.assign() simplemente asigna el valor de los objetos de origen de destino a nuestro Objeto de destino.

Código Clase

const obj1 = {
    a: 'a',
    b: 'b',
    c: {
        d: 'd',
        e: 'e',
    },
};

// Shallow Copy con for
const obj2 = {};
for (prop in obj1) {
    obj2[prop] = obj1[prop]; 
}

// Metodos de Object para hacer Shallow Copy
const obj3 = Object.assign({}, obj1);
const obj4 = Object.create(obj1);

Momento epico para los fans del anime en el min 5:32

También podemos copiar las propiedades de un objeto usando el spread operator (…)
Ejemplo:

const foo = {
  english: 'hello',
  french: 'bonjour',
  japanese: 'konnichiwa'
};
const bar = { ...foo };

console.log(bar);
// { english: 'hello', french: 'bonjour', japanese: 'konnichiwa' }

Sin embargo, seguiríamos teniendo el problema de los objetos que están dentro de otros objetos.

const carlos = {
	name: 'Carlos',
	age: 26,
	activities: {
		sports: 'Basketball',
		videoGames: 'COD'
	}
};
const maria = { ...carlos };
maria.name = 'Maria';
maria.age = 23;
maria.activities.sports = 'Soccer';

console.log(maria);
// { name: 'Maria', age: 23, activities: { sports: 'Soccer', videoGames: 'COD' } }

console.log(carlos)
// { name: 'Carlos', age: 26, activities: { sports: 'Soccer', videoGames: 'COD' } }

Ahora entiendo por que se dice que JavaScript es un lenguaje incomprendido :p

El for loop que se aplico es para aquellos tipos de datos que no son iterables, tales como los objetos literales, la sintaxis es bastante simple.

for(item in obj){
  @code
}

Hay una sintaxis similar para aquellos tipos de datos que si son iterables, tales como strings o arrays:

for(item of arr){
  @code
}

También podemos modificar las propiedades cuando las copiamos con Object.create() de la siguiente forma

obj4.__proto__.b = "Esta es otra opcion"

Les paso un articulo que explica de forma muy clara que es el shallow copy y su contra parte el deep copy, espero y les guste y les ayude mucho! 😃
https://medium.com/@manjuladube/understanding-deep-and-shallow-copy-in-javascript-13438bad941c

🌧️ Shallow copy en JavaScript

Ideas/conceptos claves

Object.assign() copia todas las propiedades enumerables de uno o más objetos fuente a un objeto destino. Devuelve el objeto destino.

Object.create() crea un objeto nuevo, utilizando un objeto existente como el prototipo del nuevo objeto creado.

Recursos

Object.assign() - JavaScript | MDN

Object.create() - JavaScript | MDN

The Difference Between Object.create and Object.assign - CodeCalls

Apuntes

  • Para poder clonar un objeto en JavaScript “superficialmente” podemos realizarlo mediante diferentes formas

Recorriendo las propiedades del Objecto

const obj1 = {
	a: "a",
	b: "b",
};

const obj2 = {};
for(prop in obj1){
	obj2[prop] = obj1[prop]
}
  • Lo que se realiza en el código anterior es iterar el objeto a copiar y pasar los valores en el nuevo objeto.
  • Lastimosamente, cuando se trata de objetos como atributos seguimos copiando solo la referencia, como por ejemplo:
const obj1 = {
	a: "a",
	b: "b",
	c: {
		d: "d"
	}
};

Object.assign()

  • Object.assign() permite crear un nuevo objeto mediante la copia de otro
  • Recibe como parametro dos valores:
    1. El objeto inicial donde se asignaran las propiedades del objeto a copiar
    2. El objeto a copiar o asignar valores
const obj3 = Object.assign({}, obj1);
  • De igual forma los objetos como propiedades se siguen copiando las referencias

Object.create()

  • Object.create() crea un nuevo objeto, recibiendo un objeto anterior, pero todas las propiedades no estarán directamente en el objeto sino que en su prototipo
  • Recibe como parámetro el objeto a copiar
const obj4 = Object.create(obj1);
  • De igual forma sigue con el problema de que no puede copiar absolutamente un objeto
📌 **RESUMEN:** Shallow copy es copiar un objeto a nivel superficial sin tener en cuenta las otras referencias internas como propiedades que puede tener.

A mi algo algo que me sirvió mucho fue recordar la clase de Freddy del curso gratis de programación básica en la que explica muy bien como accedes a los atributos de los objetos con los ciclos for utilizando index => (instancia in objeto) donde instancia itera en el índice y of => (instancia of objeto) y en of la instancia itera sobre el objeto

I si creamos un for donde verificamos que es un objeto para crear otro for y asignar así las propiedades!

Les recomiendo usar el spread operator, el cual nos sirve para tomar una copia de objetos o incluso arreglos.

const obj1 = {
    a: "a",
    b: "b",
};
console.log(obj1)
const obj2 = {...obj1};
console.log(obj2)

Vaya lio el de copiar un Objeto

Forma1 de copiar efectivamente Objetos sin copiar la referencia al espacio en memoria del objeto copiado. const objeto2 = Object.assign({} , objeto1); ....

Estuve haciendo un experimento pequeño :

let x = [];   //array
let y = [];   //array
let z = {};  //objeto

Object.getPrototypeOf(y).constructor;
// devuelve esto :      ƒ Array() { [native code] }
Object.getPrototypeOf(z).constructor;
// devuelve esto :      ƒ Object() { [native code] }

entonces veamos que pasa :

Object.getPrototypeOf(y).constructor 
    ===
    Object.getPrototypeOf(x).constructor;
//devuelve :        true

es una observacion nos puede ser util creo.

const obj4 = Object.create(obj1);

Algo así es como entendí:

Es como si obj4 heredara de obj1 pero los cambios que se le hagan a los objetos un nivel más interno afectaran tanto al original como a la copia, que cosas raras 😐

Cuando hacemos asignación de objetos

let obj1=new Obj1();
let obj2=obj1;

Hacemos asignación por referencia.
Cuando hacemos el shallow copy, realizamos asignación de un objeto a otro como si lo hicieramos esto:

obj2.p1=obj1.p1;
obj2.p2=obj1.p2;
.
.
.
obj2.p_n=obj1.p_n;

Adentrandose mas en javascript, y saber que no funciona como conceptualmente debe hacerlo, se vuelve mas confuso, y me hace pensar “en que me metí”. Asumo que mas adelante se va a explicar como solucionar estas problemas de las copias, pero mas suena a parches que se aplican y no como solucion final.

existen dos for para objetos,

for (objeto in objetos) {} >> IN es para iterar sus propiedades
for (objeto on objetos) {} >> ON es para iterar sus valores

Cuando tenemos un ‘objeto original’ y sacamos un ‘objeto copia’ del primero, tenemos un ‘objeto copia’ con los valores de cada propiedad del ‘objeto original’.
Si dentro ‘objeto original’ vive un ‘objeto anidado original’ -> en ‘objeto copia’ se creará un ‘objeto copia anidado’.
Cada modificación que ocurra en ‘objeto copia anidado’ afectará a ‘objeto anidado original’.

·
Object.create() - JavaScript | MDN crea un objeto nuevo, utilizando un objeto existente como el prototipo del nuevo objeto creado. El valor devuelto es un nuevo objeto con el prototipo y propiedades del objeto especificado
·
Object.assign() - JavaScript | MDN copia todas las propiedades enumerables de uno o más objetos fuente a un objeto destino. Devuelve el objeto destino.
·

3. Shallow copy en Javascript

Shallow copy es una copia superficial de un objeto. Es decir, copia solo los atributos del objeto, no los objetos que contiene

const obj1 = {
    a: "a",
    b: "b",
    c: {
        d: "d",
        e: "e",
    }
}
const obj2 = {
    for(prop in obj1){
    obj2[prop] = obj1[prop]    
    }
}
//iterando por cada propiedad para que copien
// y no afecten al objeto original

1. Object.assign()

Se utiliza este metodo para copiar todas las proiedades propias ENUMERABLES(primer nivel)
de un origen a un destino

Object.assing(objetivo,... fuentes);
//Objetivo -> objeto destino
//fuentes -> objetos origen

Ejemplo:

let obj = {
    a:1
};
let copy = Object.assign({},obj);
copy.a = 2;
console.log(obj.a); //1
console.log(copy.a); //2

En el anterior ejemplo ya ambos objetos tienen asignado su propio lugar en la memoria y se comportan de manera dependient.

Podemos hacer una copia de dos o más objetos con Object.assign():

let o1 = {a:1};
let o2 = {b:2};
let o3 = {c:3};
let obj = Object.assign({},o1,o2,o3);
// nuesto objeto tiene copias de los objetos fuentes
console.log(obj); //{a:1,b:2,c:3}

//si hacemos un cambio a nuestra copia
obj.a = 4;
console.log(obj); //{a:4,b:2,c:3}

// los objetos independientes mantienen su valor
console.log(o1); //{a:1}
console.log(o2); //{b:2}
console.log(o3); //{c:3}

otro ejemplo un poco más grande:

let persona_1 = {
    nombre: "Juan",
    edad: 18,
    direccion: {
        calle: "Calle falsa",
        numero: 123
    }
};
//copiamos el objeto con shadowcopy
let persona_2 = Object.assign({},persona_1);

console.log(persona_1); //{nombre: "Juan", edad: 18, direccion: {…}}
console.log(persona_2); //{nombre: "Juan", edad: 18, direccion: {…}}
//le cambiamos el valor de nombre a persona_2
persona_2.nombre = "Pedro";

//al imprimir nos damos cuenta que ambas conservan sus otros valores
console.log(persona_1); //{nombre: "Juan", edad: 18, direccion: {…}}
console.log(persona_2); //{nombre: "Pedro", edad: 18, direccion: {…}}

//cambiamos el valor de segundo nivel
persona_2.direccion.calle = "Pitufolandia";

//nos damos cuenta que ambas se les afecto el valor de donde viven
console.log(persona_1); //{nombre: "Juan", edad: 18, direccion: {calle: "Pitufolandia", numero: 123}}
console.log(persona_2); //{nombre: "Pedro", edad: 18, direccion: {calles: "Pitufolandia", numero: 123}}

Notamos que el shallow copy puede copiar solo de manera superficial, pero no puede copiar los valores dentro de otros valores, o nivel 2, etc.
Acá un artículo más completo donde saqué la información:
JavaScript — Shallow copy and Deep copy

2. Object.create()

Se utiliza para crear un objeto nuevo, utilizando un objeto existente como prototipo.

const person = {
    isHuman: false,
    printIntroduction: function(){
        console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
    }
};
const me = Object.create(person);
me.name = "Pedro";//agregamos una propiedad al objeto "me" pero no dentro de "person"
me.isHuman = true; // hereda la propiedad que puede ser sobre escrita

me.printIntroduction(); // My name is Pedro. Am I human? true

sintaxis

Object.create(proto[, propertiesObject])
Parametros

  • proto: es el objeto que será el prototipo del nuevo objeto.
  • propertiesObject:Opcional. Si se especifica un objeto, se agregarán las propiedades del objeto a la nueva instancia.
    Fuentes:
    JavaScript — Object.create()

const objeto3 = Object.create(objeto1);

Eso estuvo increiblemente confuso

Jaja, puede ser un error o un feature, creo que esa respuesta es: siempre un error