Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Copiar y modificar objetos en JavaScript

8/23
Recursos

En JavaScript tenemos diferentes formas de copiar y modificar elementos o variables, normalmente, basta con asignar dos variables e indicar que la segunda es igual a la primera:

let a = 1
let b = a

console.log(a, b) // 1, 1

De esta forma podemos copiar el valor de otra variable y realizar modificaciones más adelante:

let a = 1
let b = a
b += 1

console.log(a, b) // 1, 2

Sin embargo, todo esto cambia cuando trabajamos con objetos. Así como aprendimos en la clase anterior, los objetos se comportan distinto al resto de datos primitivos dentro de JavaScript.

Cuando asignamos el valor de una variable de tipo objeto a otras variables, en realidad, estamos copiando la referencia al objeto inicial. Esto quiere decir que, a pesar de que modifiquemos la copia de nuestras variables de tipo objeto, en realidad, estamos modificando el objeto original y, por lo tanto, todas las variables con la referencia a este objeto que acabamos de modificar:

let car = {
        color: 'red',
        year: 2019,
        km: 0,
}

let car2 = car
car2.color = 'blue'

console.log(car, car2) // ambos objetos tienen color azul, no solo `car2`

En vez de copiar los valores de nuestros objetos, cuando utilizamos el = lo que copiamos es la referencia al objeto con sus respectivos valores. Esto lo podemos solucionar utilizando la función Object.assign:

let car = {
        color: 'red',
        year: 2019,
        km: 0,
}

let car2 = Object.assign({} , car)
car2.color = 'blue'

console.log(car, car2) // `car` es de color rojo y `car2` de color azul

Sin embargo, este método no es suficiente para copiar y modificar objetos con subobjetos por el mismo problema de las referencias. La mejor manera copiar los valores de nuestros objetos en vez de sus referencias es utilizando las funciones JSON.parse y JSON.stringify:

let car = {
        color: 'red',
        year: 2019,
        km: 0,
        owner: {
                name: 'David',
                age: 25
        }
}

let car2 = JSON.parse(JSON.stringify(car))
car2.owner.age += 1

console.log(car, car2) // el dueño de `car2` es un año mayor al dueño de `car`

Aportes 39

Preguntas 2

Ordenar por:

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

Object.assign({}, car)

Solo copia los datos por valor en el primer nivel de propiedades, mientras que los objetos de los siguientes niveles son asignados por referencia, de la misma manera que si se hiciera con " = "

Esta clase me voló la cabeza. Ya había utilizado JSON.parse y JSON.stringify pero no tenia ni idea de su utilidad para copiar y modificar objetos y objetos de objetos. ¡Bravo! 👏👏👏

Esta es otra forma de crear un copia del objeto original:

let car = { color: 'Black', year: '2019', km: 0 }
// Copiando car a newCar sin hacer referencia al mismo pointer
let newCar = { ...car }

Referencia:
Curso de fundamentos de javascript de Platzi 😃

let persona = {
    nombre: 'MAR',
    apellido: 'AR',
    edad: 24,
    datos: {
        carrera: 'ING'
    }
}

let personaCopy = {
    ...persona,
    nombre:'JE'
}

console.log(personaCopy);
console.log(persona);

Los problemas que genera el manejo de datos por referencia, cuando su valor no puede ser predecible o cuando el comportamiento es inesperado a lo largo del programa, está relacionado con la mutabilidad de estados.
¡Seguramente lo vemos más adelante!

JSON.stringify realmente recibe 3 parámetros de los cuales son

value : Cadena a convertir en JSON.

replace : Este parámetro es opcional, Una función que altera el comportamiento del proceso de conversión a cadena de texto

space : este puede ser un número el cual determina la identación de la cadena.

Documentación de JSON.stringify

En caso de que tenga un objeto así:

let car = {
  color : 'blue',
  brand : 'bmw',
  owner : {
    name : 'Ramón',
    saludar : () => console.log('Hola mundo')
  }
}

Como vemos, este objeto tiene otro objeto dentro que posee una función “saludar” y si hago un JSON.stringify de este objeto imprime:

{"color":"blue","brand":"bmw","owner":{"name":"Ramón"}}

¿Cuál es la manera más óptima de copiar este objeto por valor? En este caso es preferible utilizar una clase e ir creando instancias de esta clase? ¿O existe otra manera sin necesidad de crearla?

El método JSON.stringify() convierte un valor dado en JavaScript a una cadena JSON y El método JSON.parse() analiza una cadena de texto como JSON.

Hoy en dia una forma mas simple de hacer una copia de un objeto es la siguiente:

const newCar = {...car}

Que complicado puede llegar a ser copiar objetos >.< yo lo hago con el spread operator pero no estoy seguro de que sea la forma más eficiente

Al momento de hacer

JSON.parse(JSON.stringify({}))

si es solo un objeto no hay problema. Les recomiendo esta lectura para que entiendan en que momentos es conveniente hacer eso o hacer un deepclone

let car = {
color: ‘red’,
km: 0,
year: 2019
};
let newCar = {…car}; // crear una copia de car, utilizando el Spread Operator

https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Operadores/Spread_operator

También Pueden usar desetructuración para clonar Objectos y Arreglos:

a = { name: 'MAR' }
b = { ...a }

Estos conocimientos están muy bien para cuando trabajamos con estados en Redux.

La Forma mas efectiva para copiar los objetos es utilizando los métodos :
JSON.parse(JSON.stringify(objetoAcopiar))
pues nos permitirá copiar todos los niveles que tenga nuestro objeto.
Así mismo poder alterarlos.

let newCar1 = JSON.parse(JSON.stringify(car1));
console.log(car1, newCar1);

newCar1.year = 2000;
newCar1.owner.age = 26;
newCar1.owner.name = "Jesusito";
console.log(car1, newCar1);

Nunca me había topado con algún problema de querer modificar los valores de un objeto anidado.

vaya que este TRUCO no me lo sabia

let car = {
        color: 'red',
        year: 2019,
        km: 0,
        owner: {
                name: 'David',
                age: 25
        }
}

let car2 = JSON.parse(JSON.stringify(car))
car2.owner.age += 1

console.log(car, car2)

Recomiendo el uso de lodash, para copiar objetos puedes usar .cloneDeep(value)
Pues al aplicar JSON.parse(JSON.stringify(objeto)) si este posee fechas, se transformarán en un string perdiendo su tipo.

yo prefiero utilizar el spring operator

let newCar = {...car}

Si desean correr un bloque de código de JS sin tener que ir a la consola de chome ni tener que abrir una terminar y correr el archivo con Node pueden utilizar esta extencion de vs code: Code Runner

Hay que tener cuidado con JSON.parse(JSON.stringify()) si el objeto tiene funciones adentro no pueden ser parseadas.

Me surge una duda, en caso de que dentro de nuestro objecto guardemos una función ejemplo :

let a = {
	b: function(msj){
		console.log(msj)
	}
}

como haríamos para copiar la funcion dentro ? ya que al utilizar JSON.stringify() de esta forma

let a = {
	b: function(msj){
		console.log(msj)
	}
}
JSON.stringify(a) // "{}" 

retornaríamos un objeto en donde se estarían omitiendo todas las propiedades que tengan como valor una función.

Yo tambien cerré la clase pensando que el destructuring iba a resolver esto de manera facil y eficaz, pero lo probé y no. Este hace una Shallow Copy (copia superficial).

Les dejo referencia a un post donde queda resuelta la duda.

Excelente curso! esta problematica con los objetos la tuve hace un tiempo cuando no tenia mucha idea de la programación funcional, de a ver tenido este curso antes me hubiese ahorra muchísimos dolores de cabeza

JSON.parse y JSON.stringify:

En el curso de Fundamentos de Java Script también se tocó este tema. Aqui dejo el enlace:

Cuando compiamos objetos, si trabajamos con newCar = car, estamos copiando la referencia del objeto, si trabajamos con newCar = Object.assign({}, car) copiamos el valor de la variable car (El objeto).

Se puede estudiar JSON en Platzi? Hay algún curso recomendado? Gracias.

Cuando tenemos objetos dentro de objetos, Object.assing()solo va a copiar los valores del objeto de primer nivel. Para copiar los valores completos de un objeto dentro de otro debemos utilizar JSON.parse(JSON.stringify(car))

Object.assign() => copia los valores de un objeto, pero solo los del primer nivel. Todo objeto que este dentro o anidado solo se ven a copiar las referencias.

Recomiendo leer el siguiente artículo, para tener presente que no debemos de confiarnos de los métodos de JSON.
https://medium.com/@pmzubar/why-json-parse-json-stringify-is-a-bad-practice-to-clone-an-object-in-javascript-b28ac5e36521.

crear un objeto

Excelente el uso de:

let newCar2 = Object.assign({}, car2);

Frente a:

let newCar3 = JSON.parse(JSON.stringify(car3));

También podríamos usar los Spread Operator para copiar los valores del objeto, pero solos los del primer nivel.

let car = {
  color: 'red',
  year: 2019,
  km: 0,
}

let newCar = {
  ...car,
}

newCar.year += 1

console.log(car, newCar)

Copiar objeto…

const car = {
    color: 'red',
    year:'2019',
    km:0
};

const newCar = {...car};

console.log(car, newCar);

Se podría copiar objetos haciendo destructuring?

let car = { color: 'Black', year: '2019', km: 0 }

let newCar = { ...car }

Esto me rompió la cabeza el día que me lo tope, el no poder copiar objetos así, me hubiese gustado saber el hack de parse/stringify ese día… jaja aún así, tengo una pregunta, ¿Qué sucede en este caso?:

const newCar = {
	...car
}

¿Igual se copian las referencias de los niveles más bajos?

Explicacion de JSON PARSE y JSON STRINGIFY

wow ya había utilizado ambos métodos parse y stringify pero no había captado que podían utilizarse así.