A pesquisa no "objeto clone javascript" traz alguns resultados realmente estranhos, alguns deles estão irremediavelmente desatualizados e outros são muito complexos, não é tão fácil quanto:
let clone = {...original};
Há algo de errado nisso?
A pesquisa no "objeto clone javascript" traz alguns resultados realmente estranhos, alguns deles estão irremediavelmente desatualizados e outros são muito complexos, não é tão fácil quanto:
let clone = {...original};
Há algo de errado nisso?
Respostas:
Isso é bom para clonagem superficial . A propagação do objeto é uma parte padrão do ECMAScript 2018 .
Para clonagem profunda, você precisará de uma solução diferente .
const clone = {...original}
clone raso
const newobj = {...original, prop: newOne}
para adicionar de forma imutável outro suporte ao original e armazenar como um novo objeto.
JSON.parse(JSON.stringify(input))
JSON.parse(JSON.stringify(input))
não funcionará, porque se houver functions
ou infinity
como valores, ele simplesmente atribuirá null
em seu lugar. Só funcionará se os valores forem simples literals
e não functions
.
EDIT: Quando esta resposta foi publicada, a {...obj}
sintaxe não estava disponível na maioria dos navegadores. Atualmente, você deve estar bem em usá-lo (a menos que precise dar suporte ao 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 }
No entanto, isso não fará um clone profundo. Ainda não existe uma maneira nativa de clonagem profunda.
EDIT: Como o @Mike 'Pomax' Kamermans mencionado nos comentários, você pode clonar profundamente objetos simples (por exemplo, sem protótipos, funções ou referências circulares) usando JSON.parse(JSON.stringify(input))
JSON.parse(JSON.stringify(input))
é um clone profundo adequado. No entanto, no momento em que protótipos, funções ou referências circulares estão em jogo, essa solução não funciona mais.
Se os métodos utilizados não estiverem funcionando bem com objetos que envolvem tipos de dados como Data , tente este
Importar _
import * as _ from 'lodash';
Objeto de clone profundo
myObjCopy = _.cloneDeep(myObj);
import _ from 'lodash';
é suficiente. Mas +1 na resposta "não reinvente a roda".
se você não quiser usar o json.parse (json.stringify (object)), poderá criar cópias recursivas de valores-chave:
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;
}
Mas a melhor maneira é criar uma classe que possa retornar um clone dele mesmo
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) }
}
Seguindo a resposta de @marcel, descobri que algumas funções ainda estavam ausentes no objeto clonado. por exemplo
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 || {};
}
});
}
onde no MyObject eu poderia clonar methodA, mas o methodB foi excluído. Isso ocorreu porque está faltando
enumerable: true
o que significava que não apareceu em
for(let key in item)
Em vez disso, mudei para
Object.getOwnPropertyNames(item).forEach((key) => {
....
});
que incluirá chaves não enumeráveis.
Também descobri que o protótipo ( proto ) não era clonado. Por isso acabei usando
if (obj.__proto__) {
copy.__proto__ = Object.assign(Object.create(Object.getPrototypeOf(obj)), obj);
}
PS: Frustrante não conseguir encontrar uma função incorporada para fazer isso.
Você pode fazer assim também,
let copiedData = JSON.parse(JSON.stringify(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.
Mas Object.assign () não cria um clone 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 consertar isso, devemos usar o loop de clonagem que examina cada valor do usuário [chave] e, se for um objeto, replicar sua estrutura também. Isso é chamado de "clonagem profunda".
Existe um algoritmo padrão para clonagem profunda que lida com o caso acima e casos mais complexos, chamado algoritmo de clonagem estruturada . Para não reinventar a roda, podemos usar uma implementação funcional da biblioteca JavaScript lodash, o método é chamado _.cloneDeep (obj) .
Todos os métodos acima não tratam de clonagem profunda de objetos nos quais está aninhado em n níveis. Não verifiquei seu desempenho em relação aos outros, mas é curto e simples.
O primeiro exemplo abaixo mostra a clonagem de objetos usando Object.assign
quais clones até o primeiro nível.
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 o objeto de clones profundos da abordagem abaixo
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
original = { a: [1,2,3] }
dá a você um clone doclone.a
ser literaloriginal.a
. Modificação, quer através declone
ouoriginal
modifica a mesma coisa , de modo nenhum, isso é ruim =)