JavaScript: The Hard Parts, v3

Non-Mutating Array Methods

Will Sentance
Codesmith
JavaScript: The Hard Parts, v3

Lesson Description

The "Non-Mutating Array Methods" Lesson is part of the full, JavaScript: The Hard Parts, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Will explains the dangers with mutating arrays or other variables passed by reference to a function. In recent updates to the JavaScript specification, new non-mutating array methods have been added, including toReversed, toSpliced, and toSorted. These new methods return a copy of the original array rather than mutating it.

Preview

Transcript from the "Non-Mutating Array Methods" Lesson

[00:00:00]
>> Will Sentance: I want to add some bonus stuff here, some extension with the latest JavaScript features. We're not going to map them out in quite the same amount of detail, but I think they're exciting and fun to see. So our copy array manipulate created a brand new array where the changes on each element were made, not changing the original array. The built-in map we just saw it. Also returns out brand new array, does not change the 123.

[00:00:26]
If we'd instead declared my array. If we'd instead declared my array is 123, and done my array.map, it would have returned out a brand new array and now my array would still be the same. We could have assigned my array.map, the call to it, the output to same result, same result would be 246, but my array would still be 123. That is vital because I do not want my functions to have consequences outside of their explicit output.

[00:01:04]
And if I'm changing the input data, that's a site that's going off over here. The output is not defined explicitly within the code's definition. Imagine if some of the key array mutate well, the key array methods in JavaScript around since day one did actually change the input array. I mean that would be, and imagine if you do a whole wave of changes in 2015, ES6, and you said, what doesn't matter?

[00:01:34]
It's our mutating array methods, we're going to leave them as long as we need. Well, that would be what happened. Some of the built-in major methods in JavaScript actually do the work on the array directly. The one that they're being run on. Yep, key ones reverse sort and splice, but don't panic. Even though it's a crime. Do not panic. Fortunately we now have some new array methods built in that do not mutate, do not change their input array.

[00:02:09]
I'll keep it fairly simple here, but I will show our memory. So in our memory we're declaring, you know, array 1 is our 123, we have array 2. Which is also 123, perhaps unhelpfully, maybe helpfully, I'm not sure. Now, the built-in methods here allow us to take our array 1, which we know is 123, and using this dot notation, we'll see all of this later on, run some built-in code. We've got parens on the end to show we're running some code, and that is going to head off to some built-in functions available to us in JavaScript.

[00:02:50]
We'll see more of them in the rest of the session, that we can use on this 123 here. We find out about these functions in, as we heard from Tenzin, in the documentation, or in ChatGPT and so we have reverse, splice and sort. These are as old as time, they're built into JavaScript, their problem is that they change our input array. So when we run array one.reverse and call it with parens, we're not getting a return value from this that we can assign to a new array with the array reversed, instead, we are going to mutate, change our input array, and that may not seem like the end of the world.

[00:03:45]
But if we're wanting to, for example, take a list of tweets, songs or Spotify, whatever, and we know we're going to want to display them, but maybe we want to display them in reverse order, if we're running a reverse function on them in order to then display them in reverse order, we definitely do not want to reverse the underlying data. Most all of the time, we do not want to reverse our original underlying data, because we're going to use that data when we are reversing it to be displayed or to be passed to some other evaluation, not to actually change the intrinsic data.

[00:04:18]
Especially in a language that's a lot of UI, you know, stuff that the users see, a lot of the time it's not trying to actually manipulate the data itself, but to take the data and manipulate it for display. So even more in UI oriented environments, you don't want to change underlying data, because you're constantly changing how the user sees it, but please don't change the underlying. So the fact that the built-in methods were nevertheless mutating, changing the underlying data is pretty odd.

[00:04:52]
So our first call to reverse will change the input data and replace it with 321. And next call to splice, and again I'm not here to sort of dig into the splice method design, but it takes a number of elements we want to change at a position we want to change them, or takes a position we want to change them and the number we want to change, and then it gives us the number we want to change at that position, so our 321, taking in 116, is going to find position 1 in the array, so these two are fine, find position 1 in the array, change one element at that point, which is to be replaced with the number 6.

[00:05:47]
OK, and then our sort is going to then order those automatically by our numeric hierarchy. Do we like this? Everybody? A big no, exactly. So what are we grateful that JavaScript in under 30 years, no, yeah, under 30 years. This is a really fast update. They added non-mutating array methods, like the map or copy array and manipulate that we just made. Inside of to reverse, to splice and to sorted, what is happening?

[00:06:19]
The same has happened in our copy array and manipulate. We're creating a brand new array inside of it, into which we're putting the changed elements, the updated elements. OK, so let's do that fairly quickly, we have array 2 is 123. We are then going to call on array 2 the to reversed method, which is going to evaluate to a brand new array 321. Well, we don't want to lose it, we're going to store it into a new label, reversed, 321.

[00:07:12]
I then I'm going to call on the original array 2 again, our spliced, and it's going to, oh geez, it's going to take our, hold on, I got my changes right here, yeah, it's going to take my position on the 1230, OK, this is hard to track. It's going to take out 123 and insert in the warmth position, the number 6, so we get 163 in to spliced. OK, so spliced, a brand new array with 163, and then finally, sorted is going to again take in our 123 and it's going to apply sort to it, well, it's already numerically sorted in ascending order, and so sorted is going to be 123, so, hooray.

[00:08:07]
Whereas our array 1 has been fully mutated at this point to 136, our 123 is long gone for array one, our array 2 is still 123, our reversed has done the reversing in a new array, our splice has done the splicing in a new array, our sorted is done in a new array. And even better, we don't worry that we can't, we don't need to save all these labels separately, we could also know that the output according to reversed will be 321, and then we could call on that to spliced.

[00:08:41]
Skip the saving individual labels, we could call on that to sorted, and each time we could then run it on the mutated array, but it's a brand new mutated array, meaning our array 2 stays fixed. OK, in fact, probably I should have shown it that way, right, to show that we actually can still do all those changes mutating through, but our array 2 would have stayed fixed. OK, another interesting set of new functions, and again, we're not, I don't think I will diagram these out so much as to show you that these innovations keep happening in JavaScript.

[00:09:20]
This is a sort of fun extension. These innovations keep happening in JavaScript, this one from ES 2019, more 2023 and 2024. We have an ever more useful band of functions, and the idea with all of these is not to get hung up and say, oh my goodness, wow, the language is becoming harder to follow, but instead to go, great, I have some more built-in functions that I can go and read about in the docs as I need them.

[00:09:44]
So we have the ability to flatten, again, definitely non-mutating. I guarantee you if this had been created in the old days, it 100% would have been changing the original array, but here if we have an array containing another array inside of it, we can call the flatten, the flat method on it, and that will then take out the subarray and assign it as individual elements in the main array, so our 12, subarray 122 becomes a single array, 1212, 2.

[00:10:23]
In this case we only had to go 1 layer deep, this flatten function, this flat function will actually allow us to go as many deep as we like, we can pass in infinity. Which is a terrible name for it, it defaults to one in this case, but we can pass in and go as deep as we want, taking in multiple sub-arrays. Does the depth tell you how many layers you get out or how many you want to unpack, exactly, yeah, yeah.

[00:10:50]
You're going to get one layer out, that's the sort of flattening it is to get one layer out, that was added in 2019, 2023, we got, just my point again is to show we've got ongoing innovation in our array methods. We've got one here that allows us to find the last index, the last placing of a number in a list, in an array. Going backwards. So rather than fighting first index, in this case, we run a, in this case, I put an anonymous function here that takes in each element of the array going backwards, starting with the last one, and runs a function on it.

[00:11:28]
In this case, it's taking the element and then assess, is it equal to 2. If it is, you're going to return true. If it's not, you're going to return false. In the very first case of our find last index, it hits a 2, it returns true, and it's going to return out index 4 in our flattened array, 12122, because the first 2 that it comes across is at position 4 in our 5 element array, 01234, there you go.

[00:12:00]
OK, and our last one here that's just been released and is actually a very popular function in SQL. Again, it's just to say that JavaScript continues to add, and, hard parts is never about laundry lists of features, so this is purely a little extension. Hard Parts is about a mental model, but it's just to see that JavaScript continues to add higher-order functions, ones that we can pass in another function to, that do not change the input array, and here's another one.

[00:12:47]
This is one that will allow us to take a list of values. In this case, we took in our flattened 12122, right, the result of running the flat on the deep array, so 12122. And we can evaluate each element by passing in this odd or even function. And the two labels, or actually as many labels as we return, it's quite a sophisticated function under the hood, this group by, as many labels as we return will be the labels in an object that gets returned from our group by function.

[00:13:24]
So here, we had just even and odd, if we were to have a 3 label output, if this, then this label, if this, then this label, else, if this, then this label. We would have had 3 labels, and each of them, the, in this case, value that was associated with even, will go into the even array, the value that was associated with odd will go into the odd array. And folk, again, this is not a chance to map through the group by function so much as to say our higher-order functions are everywhere.

[00:14:00]
They make up a major part of JavaScript's array methods, and they make for readable code, look at how nice that is, group by this array, and then this condition, or this function that's running a conditional. And they do not, at least now, mutate, change the input array. Just as our copy array and manipulate did not either. It created a brand new array, it took in some instructions that were going to then be applied to each element of that array, returned out that new array with all of those changed elements, and that is our standard model in a vast amount of JavaScript array methods.

Learn Straight from the Experts Who Shape the Modern Web

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