tamaño recorrer objetos objeto imprimir eliminar elementos elemento buscar array agregar javascript ecmascript-6 javascript-objects

javascript - recorrer - ¿Es esta una buena manera de clonar un objeto en ES6?



recorrer array de objetos javascript (7)

EDITAR: cuando se publicó esta respuesta, la sintaxis {...obj} no estaba disponible en la mayoría de los navegadores. Hoy en día, deberías estar bien usándolo (a menos que necesites soportar IE 11).

Use Object.assign.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

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

Sin embargo, esto no hará un clon profundo. Todavía no existe una forma nativa de clonación profunda.

EDITAR: Como @Mike ''Pomax'' Kamermans mencionó en los comentarios, puede clonar objetos simples (es decir, sin prototipos, funciones o referencias circulares) usando JSON.parse(JSON.stringify(input))

Buscar en Google el "objeto de clonación de JavaScript" trae resultados realmente extraños, algunos de ellos están desactualizados y otros son demasiado complejos, ¿no es tan fácil como:

let clone = {...original};

¿Hay algo malo con esto?



Si los métodos que usó no funcionan bien con objetos que involucran tipos de datos como Fecha , intente esto

Importar _

import * as _ from ''lodash'';

Objeto clon profundo

myObjCopy = _.cloneDeep(myObj);


Siguiendo la respuesta de @marcel, encontré que todavía faltaban algunas funciones en el objeto clonado. p.ej

function MyObject() { var methodAValue = null, methodBValue = null Object.defineProperty(this, "methodA", { get: function() { return methodAValue; }, set: function(value) { methodAValue = value || {}; }, enumerable: true }); Object.defineProperty(this, "methodB", { get: function() { return methodAValue; }, set: function(value) { methodAValue = value || {}; } }); }

donde en MyObject pude clonar el método A pero se excluyó el método B. Esto ocurrió porque falta

enumerable: true

lo que significaba que no apareció en

for(let key in item)

En cambio, cambié a

Object.getOwnPropertyNames(item).forEach((key) => { .... });

que incluirá claves no enumerables.

También descubrí que el prototipo ( proto ) no estaba clonado. Para eso terminé usando

if (obj.__proto__) { copy.__proto__ = Object.assign(Object.create(Object.getPrototypeOf(obj)), obj); }

PD: Frustrante que no pude encontrar una función integrada para hacer esto.


Todos los métodos anteriores no manejan la clonación profunda de objetos donde está anidada en n niveles. No verifiqué su rendimiento sobre otros, pero es breve y simple.

El primer ejemplo a continuación muestra la clonación de objetos usando Object.assign que clona hasta el primer nivel.

var person = { name:''saksham'', age:22, skills: { lang:''javascript'', experience:5 } } newPerson = Object.assign({},person); newPerson.skills.lang = ''angular''; console.log(newPerson.skills.lang); //logs Angular

Usando el siguiente enfoque clones profundos objeto

var person = { name:''saksham'', age:22, skills: { lang:''javascript'', experience:5 } } anotherNewPerson = JSON.parse(JSON.stringify(person)); anotherNewPerson.skills.lang = ''angular''; console.log(person.skills.lang); //logs javascript


si no desea usar json.parse (json.stringify (objeto)), puede crear copias recursivamente de valor clave:

function copy(item){ let result = null; if(!item) return result; if(Array.isArray(item)){ result = []; item.forEach(element=>{ result.push(copy(element)); }); } else if(item instanceof Object && !(item instanceof Function)){ result = {}; for(let key in item){ if(key){ result[key] = copy(item[key]); } } } return result || item; }

Pero la mejor manera es crear una clase que pueda devolver un clon de sí mismo

class MyClass{ data = null; constructor(values){ this.data = values } toString(){ console.log("MyClass: "+this.data.toString(;) } remove(id){ this.data = data.filter(d=>d.id!==id) } clone(){ return new MyClass(this.data) } }


We can do that with two way: 1- First create a new object and replicate the structure of the existing one by iterating over its properties and copying them on the primitive level. let user = { name: "John", age: 30 }; let clone = {}; // the new empty object // let''s copy all user properties into it for (let key in user) { clone[key] = user[key]; } // now clone is a fully independant clone clone.name = "Pete"; // changed the data in it alert( user.name ); // still John in the original object 2- Second we can use the method Object.assign for that let user = { name: "John" }; let permissions1 = { canView: true }; let permissions2 = { canEdit: true }; // copies all properties from permissions1 and permissions2 into user Object.assign(user, permissions1, permissions2); -Another example let user = { name: "John", age: 30 }; let clone = Object.assign({}, user); It copies all properties of user into the empty object and returns it. Actually, the same as the loop, but shorter.

Pero Object.assign () no crea un clon profundo

let user = { name: "John", sizes: { height: 182, width: 50 } }; let clone = Object.assign({}, user); alert( user.sizes === clone.sizes ); // true, same object // user and clone share sizes user.sizes.width++; // change a property from one place alert(clone.sizes.width); // 51, see the result from the other one

Para solucionarlo, debemos usar el ciclo de clonación que examina cada valor de usuario [clave] y, si es un objeto, replicar también su estructura. Eso se llama una "clonación profunda".

Existe un algoritmo estándar para la clonación profunda que maneja el caso anterior y casos más complejos, llamado algoritmo de clonación estructurada. Para no reinventar la rueda, podemos usar una implementación funcional desde la biblioteca de JavaScript, lodash el método se llama _.cloneDeep(obj) .