Check out a free preview of the full Enterprise Architecture Patterns course

The "Immutability" Lesson is part of the full, Enterprise Architecture Patterns course featured in this preview video. Here's what you'd learn in this lesson:

Lukas explains how to use immutable methods to create new items, update existing items, or delete an item within an array. Each of these immutable operations returns a new array and avoids a shared mutable state. This segment also discusses how to use the Object.freeze method.


Transcript from the "Immutability" Lesson

>> Now, we're gonna take a quick little segue here, and I wanna talk about immutable operations, this is very important. So if you've ever used array, push, I'm guilty, I've done it a bazillion times. Unfortunately, that's mutable. That's bad. If you ever needed to update something in an array, array.

splice. We just chop some up put something else in, but it is mutable. Now if you wanna delete something similar Splice it out you're done and these are mutable operations. Now. Before I go to this next slide, I wanna say that it Initially when I started. Learning about immutable operations.

I'm like, my gosh, that's gonna be so hard to do. I have to learn this new fancy way to change these things without really changing them, and I had a bad attitude. And then I realized, that it's actually. The same amount of work if not less and so Dan Abramoff has a free egghead course on Redux and I believe it's like video 16, 17 or 18 in there, he starts talking about the immutable equivalent of the immutable operate or mutable operations, and it was just like [SOUND] And so this is where I realized that to switch from a mutable mindset, to an immutable mindset, really was not much of a shift at all.

It's just using a slightly different toolset, is well is I'm imagining somebody Is saying, Well, why does this matter? Like why would we actually care about doing an immutable operation versus immutable operation? And there's a couple reasons. So one, and the big one is that in JavaScript. The JavaScript runtime, it garbage collects on, essentially memory pointers and that when you create a variable and you assign something to it, you're basically allocating a piece of memory and you're saying, in this memory, I'm going to store this thing.

Well if you want to evaluate if that's changed or not, and you've done it via a mutable operation, that you actually have to inspect the contents of that memory space to see if it's changed. So where this became a real problem, and this is where I think react really changed the game.

Is Angular j s. It would essentially when it was evaluating the DOM, it would go through and do this deep comparison. Now imagine you have an array of, I don't know, let's just say 100 objects and you need to figure out if an object in that array has changed.

Well, if you mutate the object, the only way that you can know that a change is you have to compare it with the previous value that can get very, very expensive. On the other hand, if you return a new object, you get a new memory pointer and so if you want to know if something has changed and you've done it in an immutable fashion, all you have to do is compare the memory pointer.

And if the memory pointer has changed, then you know something has happened and you just refresh. And so purely from a garbage collection standpoint, from a. Did this change or not? And do I need to do a deep comparison? Evaluating the memory pointer. Being set by returning a new object versus mutating an existing object counterintuitively is a lot faster.

Now, the other piece is that when you have These immutable operations. In other words, I have this thing I'm returning this new result. And it allows you to memorize the previous result. And then you can start to kind of time travel of like this was the previous result.

This was the previous result. And you're able to just say, I did this thing. I didn't want it and I'm going to just put it back. And no harm, nothing is done. So a really good example of this is that if you're dealing with a form, and you've bound an object to it, and you just start typing, well, anything that has a reference to that object is going to start changing in your page.

So I don't know if you've ever seen this but you basically dump like a user. Into a form, you start typing and all of a sudden, it starts changing in the list over here. The reason being is because they're pointing to the same memory pointer. And so, how you solve that is if shared mutable state is bad, and shared state is okay and mutable state is okay.

It's when you get them together that things go wrong. How you solve that problem is you make if you have to do a mutation, like around a form is that you break that connection where it's you have shared state or mutable state. If you have shared mutable state, you need to make it not shared and mutable and so what you can do here is as you pass something into like a component.

You just create a copy of it, you can mutate the copy. And then when you're done, you can either save it or throw it away. So this is why this was a three minute kind of a dialogue. why this matters is for performance reasons. It's for having kind of a ledger or being able to undo things and It prevents some really interesting things in terms of like distributed state et cetera.

So with that said without further ado, immutable operations. So let's take push and we're going to replace this with concat And a helpful way that you can find out is this immutable or not, is if you go to the MDN Mozilla Developer Network. So this is typically where if I'm reading up on an API, this is what I use.And you look at concat and it says concat method is used to merge two or more arrays.

So far, so good. This method does not change the existing arrays, but instead returns a new array. And that is the key right there as you're reading the documentation on an operation or a method, and it says instead returns. You can be like, aha, that's immutable. Now, on the example at the top, what we have is we have brackets.

So this is shorthand is we're saying create a new array, and then spread out these properties inside of this new array. So this is just a fancy newfangled way to do this. This is actually what I use quite often. And essentially you're, instead of having to use the operator to create the rate, you're just doing the shorthand and just spreading everything out in sight of it.

Next, all right, I need to update an item in a collection. How do I do that? Well two ways are you actually use a combination of two methods. So the first is map and then the second is object data science. So, the map method creates a new so anytime you create a new returns a new array with the results of calling a provided function on every element in this array so it loops over, it performs a function and then it return a brand new array.

Immutable. Now, object that assign is used to copy all the immutable own properties from one source basically to another. It will return the target object. So in this case, if you look at object dot assign, we're starting with a brand new object, the curly braces, and it's just copying everything over to that.

So this is kind of you can also use a spread operator but this is how this works. Now this works for a shallow copy. For me personally, I've never had this be a problem. In other words, if you need a copy an array of complex objects and you need to actually clone the complex objects, like there's libraries for that.

So I would say rammed a Immutable JS, but if you don't need that or you have fairly shallow objects, then I recommend just using object and assign or spread the object into a new array again. Every time I bring this up somebody does mention that it is it's only a shallow copy and this is true in a lot of cases.

This will be fine if you have a fairly flat data. Then it's no problem at all, barely an inconvenience. Now delete this one is super easy filter. The filter method creates drumroll the new array with all the elements that pass the test implemented by the provided function. And so if you wanna delete something, all you do is you say, hey, filter over this array and return everything that does not match the thing that I want to delete.

Boom. Done. Problem solved. All right. One last kind of bonus thing that I think is interesting. Occasionally I'll use it that the object dot freeze method. If you want to, if you're developing something or you wanna free something from being mutated, then this is a way to do this.

So, In essence, the object is made effectively immutable. So some it's just cool to know it's there if you want to test like, hey, like, am I mutating this? Well freeze it and see

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