Poiché gli oggetti in JavaScript sono valori di riferimento, non puoi semplicemente copiare usando=
. Ma non preoccuparti, ecco 3 modi per clonare un oggetto
# Gli oggetti sono tipi di riferimento
La tua prima domanda potrebbe essere, perché non posso usare=
. Vediamo cosa succede se lo facciamo:
const obj = { one: 1, two: 2 };const obj2 = obj;console.log( obj, // {one: 1, two: 2}; obj2, // {one: 1, two: 2};);
Finora, entrambi gli oggetti sembrano produrre la stessa cosa. Quindi nessun problema, giusto., Ma vediamo cosa succede se modifichiamo il nostro secondo oggetto:
const obj2.three = 3;console.log(obj2);// {one: 1, two: 2, three: 3}; <-- ✅console.log(obj);// {one: 1, two: 2, three: 3}; <-- 😱
WTH?! Ho cambiato obj2
ma perché è stato influenzato anche obj
. Questo perché gli oggetti sono tipi di riferimento. Quindi, quando usi =
, ha copiato il puntatore nello spazio di memoria che occupa. I tipi di riferimento non contengono valori, sono un puntatore al valore in memoria.
Se vuoi saperne di più su questo, dai un’occhiata al corso Zhu Watch e Code di Gordon. E ‘ libero di iscriversi e guardare il video “Confronto con gli oggetti”., Dà una spiegazione super impressionante su di esso.
# 1. Usando Spread
Usando spread clonerai il tuo oggetto. Nota che questa sarà una copia superficiale. A partire da questo post, l’operatore di diffusione per la clonazione di oggetti è nella fase 4. Quindi non è ancora ufficialmente nelle specifiche. Quindi, se dovessi usarlo, dovresti compilarlo con Babel (o qualcosa di simile).
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = { ...food };console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
# 2. Utilizzando Oggetto.assegna
In alternativa,Object.assign
è nel rilascio ufficiale e creerà anche una copia superficiale dell’oggetto.,
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = Object.assign({}, food);console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
Nota il vuoto {}
come primo argomento, questo ti assicurerà di non mutare l’oggetto originale
# 3. Usando JSON
Questo modo finale ti darà una copia profonda. Ora dirò, questo è un modo rapido e sporco di clonazione profonda di un oggetto. Per una soluzione più robusta, consiglierei di usare qualcosa come lodash
const food = { beef: '🥩', bacon: '🥓' };const cloneFood = JSON.parse(JSON.stringify(food));console.log(cloneFood);// { beef: '🥩', bacon: '🥓' }
# Lodash DeepClone vs JSON
Ecco un commento dalla comunità. Sì, è stato per il mio post precedente, Come clonare in profondità un array ., Ma l’idea si applica ancora agli oggetti.
Alfredo Salzillo: Mi piacerebbe che tu notassi che ci sono alcune differenze tra deepClone e JSON.stringify / analisi.per saperne di piùstringify / parse funziona solo con Numero e Stringa e Oggetto letterale senza proprietà funzione o simbolo.
Ecco un esempio:
@OlegVaraksin : Il metodo JSON ha problemi con dipendenze circolari. Inoltre, l’ordine delle proprietà nell’oggetto clonato potrebbe essere diverso.,
# Shallow Clone vs Deep Clone
Quando ho usato spread...
per copiare un oggetto, sto solo creando una copia superficiale. Se l’array è nidificato o multidimensionale, non funzionerà. Ecco il nostro esempio useremo:
const nestedObject = { flag: '🇨🇦', country: { city: 'vancouver', },};
# Copia Superficiale
clonare il nostro oggetto mediante diffusione:
const shallowClone = { ...nestedObject };// Changed our cloned objectshallowClone.flag = '🇹🇼';shallowClone.country.city = 'taipei';
Così abbiamo cambiato il nostro oggetto clonato cambiando la città. Vediamo l’uscita.
console.log(shallowClone);// {country: '🇹🇼', {city: 'taipei'}}console.log(nestedObject);// {country: '🇨🇦', {city: 'taipei'}} <-- 😱
Una copia superficiale significa che il primo livello viene copiato, i livelli più profondi sono referenziati.,
# Deep Copy
Prendiamo lo stesso esempio ma applicando una copia profonda usando “JSON”
Come puoi vedere, la copia profonda è una copia true per gli oggetti nidificati. Spesso la copia superficiale del tempo è abbastanza buona, non hai davvero bisogno di una copia profonda. E ‘ come una pistola sparachiodi contro un martello. Il più delle volte il martello è perfettamente a posto. Utilizzando una pistola sparachiodi per alcune piccole arti e artigianato è spesso caso di un eccessivo, un martello è bene. Si tratta di utilizzare lo strumento giusto per il lavoro giusto
# Performance
Sfortunatamente, non posso scrivere un test per lo spread perché non è ancora ufficialmente nelle specifiche., Tuttavia, l’ho incluso nel test in modo da poterlo eseguire in futuro 😝. Ma il risultato mostra Object.assign
è molto più veloce di JSON
.
Test delle prestazioni
# Ingresso comunità
# Oggetto.assegna vs Spread
@d9el : è importante notare quell’Oggetto.assign è una funzione che modifica e restituisce l’oggetto di destinazione. Nell’esempio di Samantha usando quanto segue,
const cloneFood = Object.assign({}, food);
{}
è l’oggetto che viene modificato., L’oggetto di destinazione non è referenziato da alcuna variabile a quel punto, ma poichéObject.assign
restituisce l’oggetto di destinazione, siamo in grado di memorizzare l’oggetto assegnato risultante nella variabilecloneFood
. Potremmo cambiare il nostro esempio e usare quanto segue:
const food = { beef: '🌽', bacon: '🥓' };Object.assign(food, { beef: '🥩' });console.log(food);// { beef: '🥩', bacon: '🥓' }
Ovviamente, il valore di beef
nel nostro oggetto food è sbagliato, quindi possiamo assegnare il valore corretto di beef
usando Object.assign
., In realtà non stiamo affatto utilizzando il valore restituito della funzione, ma stiamo modificando il nostro oggetto di destinazione a cui abbiamo fatto riferimento con const food
.
Spread d’altra parte è un operatore che copia le proprietà di un oggetto in un nuovo oggetto., Se abbiamo voluto replicare l’esempio di cui sopra mediante la diffusione di modificare la nostra variabile food...
const food = { beef: '🌽', bacon: '🥓' };food = { ...food, beef: '🥩',};// TypeError: invalid assignment to const `food'
...
si ottiene un errore, perché l’uso di diffusione durante la creazione di nuovi oggetti, e pertanto l’assegnazione di un nuovo oggetto food
che è stato dichiarato con const
, che è illegale., Così si può scegliere di dichiarare una nuova variabile per contenere il nostro nuovo oggetto, come la seguente:
const food = { beef: '🌽', bacon: '🥓' };const newFood = { ...food, beef: '🥩',};console.log(newFood);// { beef: '🥩', bacon: '🥓' }
o possiamo dichiarare food
con let
o var
che ci permetterà di assegnare un nuovo oggetto:
let food = { beef: '🌽', bacon: '🥓' };food = { ...food, beef: '🥩',};console.log(food);// { beef: '🥩', bacon: '🥓' }
Grazie: @d9el
# Profondo Clone uso di Librerie Esterne
# Più Modi, utilizzando JavaScript
- @hariharan_d3v :
Object.fromEntries(Object.entries(food))
cloni oggetto.
Lascia un commento