Cercare su Google "oggetto clone javascript" porta a risultati davvero strani, alcuni sono irrimediabilmente obsoleti e altri sono troppo complessi, non è facile come solo:
let clone = {...original};
c'è qualcosa di sbagliato con questo?
Cercare su Google "oggetto clone javascript" porta a risultati davvero strani, alcuni sono irrimediabilmente obsoleti e altri sono troppo complessi, non è facile come solo:
let clone = {...original};
c'è qualcosa di sbagliato con questo?
Risposte:
Questo è utile per la clonazione superficiale . La diffusione dell'oggetto è una parte standard di ECMAScript 2018 .
Per la clonazione profonda avrai bisogno di una soluzione diversa .
const clone = {...original}
al clone superficiale
const newobj = {...original, prop: newOne}
per aggiungere immutabilmente un altro oggetto all'originale e archiviarlo come nuovo oggetto.
JSON.parse(JSON.stringify(input))
JSON.parse(JSON.stringify(input))
non funzionerà, perché se presenti functions
o infinity
come valori verranno semplicemente assegnati null
al loro posto. Funzionerà solo se i valori sono semplici literals
e non lo sono functions
.
EDIT: quando questa risposta è stata pubblicata, la {...obj}
sintassi non era disponibile nella maggior parte dei browser. Al giorno d'oggi, dovresti andare bene a usarlo (a meno che non sia necessario supportare IE 11).
Usa 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 }
Tuttavia, questo non renderà un clone profondo. Non esiste ancora un modo nativo di clonazione profonda.
EDIT: Come KamMans 'Pomax' di @Mike menzionato nei commenti, puoi clonare in profondità oggetti semplici (es. Nessun prototipo, funzione o riferimento circolare) usando JSON.parse(JSON.stringify(input))
JSON.parse(JSON.stringify(input))
è un vero clone profondo. Tuttavia, nel momento in cui prototipi, funzioni o riferimenti circolari sono in gioco, quella soluzione non funziona più.
Se i metodi che hai utilizzato non funzionano bene con oggetti che coinvolgono tipi di dati come Date , prova questo
Importare _
import * as _ from 'lodash';
Oggetto clone profondo
myObjCopy = _.cloneDeep(myObj);
import _ from 'lodash';
è sufficiente. Ma +1 per la risposta "non reinventare la ruota".
se non vuoi usare json.parse (json.stringify (oggetto)) puoi creare copie ricorsive di valori-chiave:
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;
}
Ma il modo migliore è creare una classe che può restituire un clone di se stesso
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) }
}
In seguito alla risposta di @marcel ho scoperto che mancavano ancora alcune funzioni sull'oggetto clonato. per esempio
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 || {};
}
});
}
dove su MyObject ho potuto clonare il metodo A ma il metodo B è stato escluso. Ciò si è verificato perché mancante
enumerable: true
il che significa che non si è presentato
for(let key in item)
Invece sono passato a
Object.getOwnPropertyNames(item).forEach((key) => {
....
});
che includerà chiavi non enumerabili.
Ho anche scoperto che il prototipo ( proto ) non è stato clonato. Per quello ho finito per usare
if (obj.__proto__) {
copy.__proto__ = Object.assign(Object.create(Object.getPrototypeOf(obj)), obj);
}
PS: Frustrante che non sono riuscito a trovare una funzione integrata per farlo.
Puoi farlo anche in questo modo,
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.
Ma Object.assign () non crea un clone profondo
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
Per risolvere questo problema, dovremmo usare il ciclo di clonazione che esamina ogni valore dell'utente [chiave] e, se è un oggetto, replicare anche la sua struttura. Si chiama "clonazione profonda".
Esiste un algoritmo standard per la clonazione profonda che gestisce il caso sopra e casi più complessi, chiamato algoritmo di clonazione strutturata . Per non reinventare la ruota, possiamo usare un'implementazione funzionante dalla libreria JavaScript lodash, il metodo si chiama _.cloneDeep (obj) .
Tutti i metodi sopra non gestiscono la clonazione profonda di oggetti in cui è nidificato su n livelli. Non ho verificato le sue prestazioni rispetto ad altri ma è breve e semplice.
Il primo esempio di seguito mostra la clonazione di oggetti usando Object.assign
quali cloni fino al primo livello.
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 l'approccio sotto cloni profondi oggetto
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] }
ti dà un clone conclone.a
letteralmente essereoriginal.a
. La modifica attraverso siaclone
ooriginal
modifica la stessa cosa , quindi no, questo è male =)