Immutability and Pure Functions
Introduction: Why Immutability Matters
In our last lesson, we learned how to use higher-order functions like filter and map to process collections of data. You might remember that we briefly used the syntax [...transactions] before sorting a list. We did this because some JavaScript methods change the original data they are given. In functional programming, we try to avoid this behavior entirely. This concept is called immutability.
Immutability means that once a piece of data is created, it should never be changed. Instead of modifying an existing object or array, we create a brand-new copy that contains the changes we need. This approach is very important when building reliable systems, such as a banking application. If you have a record of a transaction, you want to be sure that no part of your code can accidentally change its amount or ID later on. By the end of this lesson, you will know how to update objects and lists safely using pure patterns.
The Danger Of Mutation
When we change an object directly, we call it mutation. This can lead to very confusing bugs because JavaScript passes object references by value. That means two variables can hold references to the same object, so mutating through one reference is visible through the other.
Imagine a scenario where one part of your app is calculating a total balance while another part is marking a transaction as "completed." If the second part of the code accidentally changes the amount of the transaction while updating its status, your balance calculation will suddenly be wrong. These types of "side effects" make code very difficult to test and debug because the data can change at any time from anywhere in your program. To prevent this, we treat our data as if it were carved in stone.
Pure Object Updates With The Spread Operator
To update an object without changing the original, we use the spread operator, which looks like three dots .... This operator allows us to "spread" the properties of an existing object into a new one. We can then list any properties we want to change after the spread operator, and those new values will overwrite the old ones in the new object.
In the markCompleted function, we take a transaction object called tx. Instead of saying tx.status = "completed", we return a new object wrapped in parentheses. Inside this new object, we spread the properties of tx and then specify that the status should be "completed." When we run this code, the output shows that the original transaction remains "pending," while our new version is "completed."
