Functional JavaScript First Steps


Anjana Vakil

Anjana Vakil

Software Engineer & Educator
Functional JavaScript First Steps

Check out a free preview of the full Functional JavaScript First Steps course

The "Immutability" Lesson is part of the full, Functional JavaScript First Steps course featured in this preview video. Here's what you'd learn in this lesson:

Anjana demonstrates how to use the map function to copy an array to prevent mutation. Although the new copy has prevented mutating the original Array, creating copies can increase the amount of memory required to run a program. Immutable or persistent data structures allow unchanged parts of the data to be reused throughout a program.


Transcript from the "Immutability" Lesson

>> Let's come back to that concept of immutability. That has come up several times today where we said that immutability and immutable data really go hand in hand with functional programming. And we saw that changing things especially changing things out in the world feels not functional feels pretty side effect.

Feels pretty not pure. So let's take a look at how we can think about immutability when we are doing functional programming and particularly in JavaScript. So in general, mutability causes a lot of headaches, whether you're doing functional programming, whether you've been doing sort of pseudo functional programming or whether you are sticking to plain old object oriented JavaScript.

Mutating value, so changing values in place, like changing the elements in an array in place, or changing the elements in a in an object, the values in an object in place can lead to a lot of headaches. Because you have to really think hard about What somebody might have done to change your object out from under you.

So in functional programming, and remember the aim of using functional programming is to make us happier and more productive programmers because we have less bugs. We have easier tests etcetera. What we're gonna do is we're gonna avoid mutability. We're gonna avoid mutating data or changing data in place.

And instead we're going to replace any data that we want to update with a new slightly modified version. So let's take a look. Okay, here I've got an array of some city names, which are a little bit out of date. For example, the city called Mumbai is no longer called Bombay.

So maybe I have this array of cities and I want to replace that middle value. So I use regular old JavaScript. The first index in the array, I'm going to assign a new value. And now cities is different. Okay, so that worked for me because I'm trying to work with the CRA but maybe meanwhile, my coworker over there she's working with this cities array 2 and she wasn't expecting any of the data to change.

Maybe I changed it wrong. Maybe I put an undefined value in there or maybe I put a number in there or did something that broke the assumptions that she was making about working with the cities array. And she has no way of knowing that so you have to check for everything if to check for all of those edge cases, right?

Otherwise I am going to break her code because she was not expecting me to change that cities array out from under her. So a safer way to do this is if I have this array of old cities is instead of mutating it and changing that value in place, I'm going to create a new cities array, which I can use this map operation.

And here I'm using the built in JavaScriptarray.mapsyntax, instead of our little map helper function, but you could totally do this with the more functional style map helper. That we saw how to use plenty of times earlier. So what I'm gonna do is using a map, I'm gonna go through everything in this city's array and check if it needs to be updated or not.

And that map, as we said before, that map operation returns a new array, it doesn't change the array in place. So now new cities is a totally different array with different values with some updated names. But my old cities array has not been changed. So my coworker she was working with that old cities array and making assumptions about what types of data would be in it, or what shape that data would be things like that.

I haven't missed any of that up. She is still working with the same data she was always working with, but I now have my new cities array that I can use in my code to do whatever I'm trying to do. So the idea is that avoiding mutation and creating new copies with those slight differences instead of using the same copy and changing it in place is much safer.

And also allows us to read more of that determinant, excuse me, for that more deterministic code. So that we know what is gonna happen because we're confident that no one has changed the data that we're working with. Now you might be wondering mm-hm what if those arrays are really long?

Or what have you have to make lots of updates to them does not mean that you're gonna have to make more and more and more and more and more long arrays. And isn't that gonna get kinda heavy and kinda not so performant or we gonna start using a lot of memory and also we have to take the time to copy all of that stuff every time.

What's the deal there? And it's true copying data this way, instead of changing it in place is not super efficient. We have a lot of work to do, and that takes time and it takes space. So that is a challenge for functional programming if I want all of my data to be immutable, if I want to always be returning new copies, Instead of changing things.

How can I do that in a way that's not going to immediately blow up my computer from maxing out memory or just take forever because I have to go through every array every time. So there is a solution to this in the functional programming world which is special types of data structures that are designed to be immutable, but also efficient.

And these are called immutable data structures, or sometimes persistent data structures. Those are actually two slightly different terms but they're often used interchangeably, so we're not gonna get into the subtle differences here. Use something called structural sharing. Immutable data structures allow us to represent our data in a kind of tree like structure.

So that we can reuse unchanged parts of the tree while changing the parts that we wanna update. Now, we're not gonna go into a ton of detail on this today. But suffice it to say that the core idea is this. Let's say I have some array called Zoo with a bunch of Zoo animals, little emojis and I want to update that.

I want to instead of my little bunny rabbit here at index 1, I wanna have an alien, I'm getting a really exotic alien animal in my Zoo. Instead of mutating that in place, which again, could mess up, I don't know. Maybe my Zoo keeper colleague over there is not expecting extra terrestrial animals and their code only works with terrestrial animals maybe.

So instead of changing that in place, what I can do is take my original Zoo array, break it up into this tree like structure, where now instead of an array, I've got kind of a tree of all my data. And now what I can do is copy only the nodes of the tree that I need to change to replace that value at index 1.

So before I had my array represented with these little notes, a little pairs of buddies of animals, which are then joined by these kind of intermediary nodes. And then finally I get sort of a root node that I can point to in my Zoo variable so that I can unite all of those animals.

What I'm going to do is keep all of the nodes that I don't need to change and create new a new node for any new values that I need. So in this case, I'm copying a little two item array, which is way better than copying an eight item array.

And then add some intermediate nodes that link that that new node up with the old ones that I have not changed. So what I've got here, is this yellow part of the tree here, gets to be shared by both versions. So what happens, is that I get to create new copies of my array, which is now a tree under the hood without copying everything in the array.

And we're not gonna go into ton of detail about how this works or how it's more efficient but I'm gonna leave you with some more resources later to read up on that. And a talk of mine you can watch also, to find out more about that. Suffice it to say, this really helps functional programmers, because we get to work with immutable data but still not have to copy everything every single time which would be super slow and would require tons of space.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now