Clone Objects
Tags: javascript, beginners, tutorial, webdev
Published: 2022-10-29 21:51:16

## 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: 

```javascript
const name = 'Pippo';
const newName = name; 
//ora newName ha una stringa 'Pippo'
//indipendente dalla variabile 
//da cui ha clonato il valore
```

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:

```javascript
//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);

```

output:
![console.log code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wt3tzgpfb27zr33rod12.png)



## 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

:warning:**ATTENZIONE**:warning:
**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à

```javascript
//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);

```

Output:

![code javascript code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/te9eoxd3bw4sdv62zv3j.png)

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:

```javascript
//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);

```

oppure ancora meglio possiamo usare la sintassi spread direttamente sulla variabile

```javascript
const cloneStudente = {...studente}
```

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

```javascript
//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);

```

output:

![Image output console.log](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xrzjifxmq1syioe0826c.png)

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](https://lodash.com/).

Infatti [qui](https://lodash.com/docs/4.17.15#cloneDeep) 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](https://www.jsdelivr.com/package/npm/lodash)

```html
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
```
così:

```html
<!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>
```

vediamo subito un esempio:

```javascript
//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);

```

output:


![Image output console.log](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ieu4f0rh0ztnzwra4qba.png)

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.