Muterbar och Omuterbar i JavaScript
Den här artikeln förklarar begreppen muterbar och omuterbar i JavaScript.
YouTube Video
Muterbar och Omuterbar i JavaScript
Vad är Muterbar?
Muterbar betyder att ett värde kan modifieras. Objekt och arrayer, som är referenstyper, är typiska exempel på muterbara datastrukturer.
Exempel på ett Muterbart Objekt
1let person = { name: "Alice", age: 25 };
2person.age = 26;
3console.log(person); // { name: "Alice", age: 26 }
I denna kod ändras age
-egenskapen för person
-objektet från 25
till 26
. Eftersom objekt passeras som referens, ändras innehållet på minnesadressen som lagras i person
-variabeln.
Exempel på en Muterbar Array
1let numbers = [1, 2, 3];
2numbers.push(4);
3console.log(numbers); // [1, 2, 3, 4]
I denna kod används push
-metoden för att lägga till ett nytt element 4
till den ursprungliga arrayen. Detta modifierar den ursprungliga arrayen, vilket gör det till en muterbar operation.
Exempel i en Funktion
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)
När man utför muterbara operationer inuti en funktion, modifieras även den ursprungliga arrayen.
Vad är Omuterbar?
Omuterbar betyder att ett värde inte kan modifieras. Primitiva typer är fundamentalt omuterbara.
Exempel på en Omuterbar Primitiv Typ
1let str = "hello";
2str[0] = "H";
3console.log(str); // "hello"
Försök att ändra den första bokstaven i strängen str
till H
misslyckas eftersom strängar är omuterbara.
Exempel i en Funktion
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)
Eftersom siffror är omuterbara påverkar inte operationer inuti en funktion den ursprungliga variabeln.
Omuterbara Operationer på Arrayer
Arrayer är muterbara, men att skapa en ny array istället för att modifiera den ursprungliga möjliggör omuterbara operationer.
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)
Här används spridningssyntaxen (...
) för att skapa en ny array newNumbers
. Eftersom den ursprungliga arrayen numbers
inte ändras är detta en oföränderlig operation.
Fördelar med att använda oföränderliga datastrukturer
Förbättrad förutsägbarhet
Eftersom oföränderliga data inte kan ändras är oväntade ändringar mindre sannolika, vilket minskar risken för fel.
Kompatibilitet med bibliotek baserade på oföränderlighet
Bibliotek som React
och Redux
är ofta utformade med oföränderliga data i åtanke, vilket gör hantering av tillstånd enklare när de används på rätt sätt.
Göra objekt oföränderliga med Object.freeze
Object.freeze
kan användas för att förhindra ändringar i ett objekt.
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 }
Dock utför Object.freeze
en ytlig frysning, vilket innebär att egenskaper i nästlade objekt förblir föränderliga.
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)
För att skapa ett helt oföränderligt objekt krävs en djupfrysning.
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)
Sammanfattning
- Föränderliga data kan ändras, inklusive objekt och arrayer.
- Oföränderliga data kan inte ändras, inklusive primitiva typer som strängar och nummer.
- Att använda spridningssyntax eller
map
möjliggör operationer med oföränderliga data.. Object.freeze
ochdeepFreeze
kan användas för att förhindra ändringar i objekt.- Genom att använda oföränderliga data får man mer förutsägbar och mindre felbenägen kod.
Oföränderlig design förbättrar kodsäkerhet och läsbarhet, så använd det på ett smart sätt!
Du kan följa med i artikeln ovan med hjälp av Visual Studio Code på vår YouTube-kanal. Vänligen kolla även in YouTube-kanalen.