Mutable e Immutable in JavaScript
Questo articolo spiega i concetti di mutable e immutable in JavaScript.
YouTube Video
Mutable e Immutable in JavaScript
Cosa significa Mutable?
Mutable significa che un valore può essere modificato. Oggetti e array, che sono tipi reference, sono esempi tipici di strutture dati mutable.
Esempio di un Oggetto Mutable
1let person = { name: "Alice", age: 25 };
2person.age = 26;
3console.log(person); // { name: "Alice", age: 26 }
In questo codice, la proprietà age
dell'oggetto person
viene modificata da 25
a 26
. Poiché gli oggetti sono passati per riferimento, il contenuto al indirizzo di memoria memorizzato nella variabile person
viene modificato.
Esempio di un Array Mutable
1let numbers = [1, 2, 3];
2numbers.push(4);
3console.log(numbers); // [1, 2, 3, 4]
In questo codice, il metodo push
viene utilizzato per aggiungere un nuovo elemento 4
all'array originale. Questo modifica l'array originale, rendendolo un'operazione mutable.
Esempio in una Funzione
1// Function to append a value to an array
2function append(arr, value) {
3 arr.push(value); // Modify the original array
4 console.log(arr);
5}
6
7let numbers = [1, 2, 3];
8append(numbers, 4);
9
10console.log(numbers); // [1, 2, 3, 4] (original array is modified)
Quando si eseguono operazioni mutable all'interno di una funzione, anche l'array originale viene modificato.
Cosa significa Immutable?
Immutable significa che un valore non può essere modificato. I tipi primitivi sono fondamentalmente immutable.
Esempio di un Tipo Primitivo Immutable
1let str = "hello";
2str[0] = "H";
3console.log(str); // "hello"
Tentare di cambiare il primo carattere della stringa str
in H
fallisce perché le stringhe sono immutable.
Esempio in una Funzione
1// Function to increment a number
2function increment(num) {
3 num++; // This modifies only the local copy of num
4 console.log(num);
5}
6
7let number = 10;
8increment(number);
9
10console.log(number); // 10 (original number remains unchanged)
Dato che i numeri sono immutable, le operazioni all'interno di una funzione non influenzano la variabile originale.
Operazioni Immutable sugli Array
Gli array sono mutable, ma creare un nuovo array invece di modificare quello originale consente di effettuare operazioni immutable.
1// Create an array of numbers
2let numbers = [1, 2, 3];
3
4// Create a new array by spreading the original and adding a new element
5let newNumbers = [...numbers, 4];
6
7console.log(numbers); // [1, 2, 3] (original array is unchanged)
8console.log(newNumbers); // [1, 2, 3, 4] (new array with an added element)
Qui, la sintassi spread (...
) viene utilizzata per creare un nuovo array newNumbers
. Poiché l'array originale numbers
non viene modificato, questa è un'operazione immutabile.
Vantaggi dell'utilizzo di strutture dati immutabili
Maggiore prevedibilità
Poiché i dati immutabili non possono essere modificati, le modifiche inattese sono meno probabili, riducendo il rischio di bug.
Compatibilità con librerie basate sull'immutabilità
Librerie come React
e Redux
sono spesso progettate pensando ai dati immutabili, semplificando la gestione dello stato se utilizzate correttamente.
Rendere immutabili gli oggetti con Object.freeze
Object.freeze
può essere utilizzato per impedire modifiche a un oggetto.
1// Create a frozen object (properties cannot be modified)
2const person = Object.freeze({ name: "Alice", age: 25 });
3
4// Attempt to modify a property (ignored in non-strict mode, error in strict mode)
5person.age = 26;
6
7console.log(person); // { name: "Alice", age: 25 }
Tuttavia, Object.freeze
esegue un blocco superficiale, il che significa che le proprietà degli oggetti annidati rimangono modificabili.
1// Create a frozen object with a nested object
2const user = Object.freeze({ profile: { name: "Bob" } });
3
4// Attempt to modify a nested property (this works because Object.freeze() is shallow)
5user.profile.name = "Charlie";
6
7console.log(user.profile.name); // "Charlie" (nested object is still mutable)
Per creare un oggetto completamente immutabile è necessario un blocco profondo.
1// Function to deeply freeze an object, making all nested objects immutable
2function deepFreeze(obj) {
3 Object.keys(obj).forEach(key => {
4 if (typeof obj[key] === "object" && obj[key] !== null) {
5 deepFreeze(obj[key]); // Recursively freeze nested objects
6 }
7 });
8 return Object.freeze(obj); // Freeze the top-level object
9}
10
11// Create a deeply frozen object
12const user = deepFreeze({ profile: { name: "Bob" } });
13
14// Attempt to modify a nested property (ignored)
15user.profile.name = "Charlie";
16
17console.log(user.profile.name); // "Bob" (unchanged due to deep freeze)
Riepilogo
- I dati mutabili possono essere modificati, inclusi oggetti e array.
- I dati immutabili non possono essere modificati, inclusi tipi primitivi come stringhe e numeri.
- L'utilizzo della sintassi spread o di
map
consente operazioni sui dati immutabili.. Object.freeze
edeepFreeze
possono essere utilizzati per impedire modifiche agli oggetti.- L'utilizzo di dati immutabili consente un codice più prevedibile e meno soggetto a errori.
Un design immutabile migliora la sicurezza e la leggibilità del codice, quindi sfruttalo al meglio!
Puoi seguire l'articolo sopra utilizzando Visual Studio Code sul nostro canale YouTube. Controlla anche il nostro canale YouTube.