DEV Community

Mattia Rollo
Mattia Rollo

Posted on • Updated on

Clone Objects

Cloniamo oggetti in Javascript

La clonazione di un oggetto non è così semplice come avviene con la clonazione di un valore primitivo preso da un altra variabile con valore primitivo. (1,'hello world!', true, null)

Per esempio:

const name = 'Pippo';
const newName = name; 
//ora newName ha una stringa 'Pippo'
//indipendente dalla variabile 
//da cui ha clonato il valore
Enter fullscreen mode Exit fullscreen mode

Se volessi replicare la stessa cosa con gli oggetti, non funzionerebbe come vorremmo.
Questo perchè con gli oggetti (e anche con gli array) l'associazione alla variabile avviene per RIFERIMENTO, la quale si riferisce all'oggetto: NON è l'oggetto in sè

ora vediamo un esempio:

//inizializzo una variabile che crea un oggetto 
//e proprio come gli array non è l'oggetto in se 
//ma è un riferimento all'oggetto
let studente = {
    nome: 'Mattia',
    cognome: 'Rollo',
    abilità: {
        suonare: 5,
        programmare: 5,
    }
};

//non si può clonare un oggetto facendo semplicemente
const cloneStudente = studente;

//perchè qualsiasi modifica fatta all'oggetto studente la vedrò 
//anche su cloneStudente
//esempio
studente.nome = 'Pippo';


console.log(studente)
console.log(cloneStudente);

Enter fullscreen mode Exit fullscreen mode

output:
console.log code

Quindi come cloniamo gli oggetti?

Ci sono diversi modi per clonare gli oggetti in modo che ogni copia sia indipendente dalla copia originale:

  • usando un ciclo for in, per ogni key nell'oggetto copiamo ogni singola key
  • usando Object.assign(clone,oggetto da copiare)
  • usando (...) sintassi spread

⚠️ATTENZIONE⚠️
Con queste modalità è possibile clonare un oggetto in modo efficiente SOLO se contiene soltanto delle proprietà, e non se possiede anche un altro oggetto, in tal caso dobbiamo usare un'altra procedura, o meglio, un metodo

vediamo un esempio con il ciclo for in, con un oggetto che ha soltanto delle proprietà

//qui creo un oggetto che contiene solo delle proprietà non degli
//oggetti al suo interno
let studente = {
    nome: 'Mattia',
    cognome: 'Rollo'
};
const cloneStudente = {}

//con il ciclo for copiamo ogni chiave dell'oggetto
// così facendo avremo una copia indipendete 
//dall'oggetto copiato
for(key in studente) {
    cloneStudente[key] = studente[key];
}

//infatti qualsiasi modifica all'oggetto studente
//non verrà applicata a cloneStudente
studente.nome = 'Pippo';


console.log(studente)
console.log(cloneStudente);

Enter fullscreen mode Exit fullscreen mode

Output:

code javascript code

Un pò macchinoso, vediamo invece con come sarebbe la sintassi con Object.assign() , il quale produrrebbe lo stesso output del ciclo for in visto prima:

//inizializzo una variabile che crea un oggetto 
//e proprio come gli array non è l'oggetto in se 
//ma è un riferimento all'oggetto
let studente = {
    nome: 'Mattia',
    cognome: 'Rollo'
    // abilià: {
    //     suonare: 5,
    //     programmare: 5,
    // }
};
const cloneStudente = {}

//Esempio con il metodo Object.assign()
//il primo valore nelle parentesi è l'oggetto clone (oggetto di destinazione)
//il secondo valore è l'oggetto da copiare
Object.assign(cloneStudente,studente)

//infatti qualsiasi modifica all'oggetto studente
//non verrà applicata a cloneStudente come nell'esempio
//precedente
studente.nome = 'Pippo';


console.log(studente)
console.log(cloneStudente);

Enter fullscreen mode Exit fullscreen mode

oppure ancora meglio possiamo usare la sintassi spread direttamente sulla variabile

const cloneStudente = {...studente}
Enter fullscreen mode Exit fullscreen mode

le modalità elencate qui sopra andrebbero benissimo se l'oggetto da clonare contenesse solo proprietà, ma non sempre è così.
A volte può capitare di voler clonare un oggetto che contiene un altro oggetto al suo interno, proviamo ad aggiungerne uno all'esempio di prima

//abbiamo aggiunto un oggetto all'interno dell'oggetto studente
let studente = {
    nome: 'Mattia',
    cognome: 'Rollo',
    abilita: {
        suonare: 10,
        programmare: 10,
    }
};
//cloniamo con la sitassi spread
const cloneStudente = {...studente}

//modifichiamo il primo valore
//all'interno del oggetto 'abilita'
//dentro all'oggetto studente
studente.abilita.suonare = 15;

//facciamo un console.log dei due oggetti e vediamo il risultato
console.log(studente)
console.log(cloneStudente);

Enter fullscreen mode Exit fullscreen mode

output:

Image output console.log

Come possiamo vedere la proprietà 'suonare' è cambiata sia nel oggetto copiato sia nel suo clone, infatti anche in questo caso, purtroppo, la copia avviene per RIFERIMENTO, quindi tutti e due contengono lo stesso oggetto, se ne modifichi uno si modificherà anche l'altro.

Ma quindi come facciamo?

Per fortuna qualcuno ci aveva già pensato prima di noi e ha creato una libreria apposta: lodash.

Infatti qui possiamo trovare il metodo _.cloneDeep() che ci aiuta creare dei cloni indipendenti dalla copia originale.

Per poter importare la libreria ci basta copiare il cdn da inserire nel head del nostro file index.html scariabile da jsdelivr

<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
Enter fullscreen mode Exit fullscreen mode

così:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!--cdn da copiare per usare la libreria lodash -->
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

    <link rel="stylesheet" href="css/style.css">
    <title>Document</title>
</head>
<body>

    <script src="js/script.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

vediamo subito un esempio:

//abbiamo aggiunto un oggetto all'interno dell'oggetto studente
let studente = {
    nome: 'Mattia',
    cognome: 'Rollo',
    abilita: {
        suonare: 10,
        programmare: 10,
    }
};
//cloniamo con il metodo _.cloneDeep()
// fornito dalla libreria lodash
const cloneStudente = _.cloneDeep(studente);

//modifichiamo il primo valore
//all'interno del oggetto dentro all'oggetto studente
studente.abilita.suonare = 15;

//facciamo un console.log dei due oggetti e vediamo il risultato
console.log(studente)
console.log(cloneStudente);

Enter fullscreen mode Exit fullscreen mode

output:

Image output console.log

Come possiamo notare ora se cambio valore all'oggetto 'abilita' dentro all'oggetto 'studente', non cambierà il valore di quello presente in cloneStudente, questo perchè è stata creata una copia completamente indipendente dall'originale.

Top comments (0)