Functional programming with array's higher-order functions such as filter, map, and reduce are a great way to deal with arrays and also a good foothold into functional programming because it pushes forward ideas like immutability.
However, there's a dark side to this that RxJS can save you from. To illustrate that I've set up this example. I have a source array, which is just numbers zero through five. I'm filtering to only the even numbers. Then I'm mapping to add an exclamation point, and finally I'm reducing to concatenate them all into a string. Then I'm logging the results.
When I run this, you'll see I get zero, two, and four with exclamation points all in a string. Now what could possibly be a dark side to doing things this way? To illustrate that I'm going to add in the other arguments and log them out.
Now when I run this code we'll be able to see what I'm filtering out at this step and whether or not at each step the array that I'm being passed to that step is the same as the source array.
See, when I'm filtering it is stepping through every single one of the items, and it's the same source array. That's coming up true, but when I get to the next step in my mapping the source is not the same. The array I'm getting is actually different, so the filter's creating a brand new array for me.
That's good because it pushes forward the idea of immutability. However, it's bad because that means I'm allocating a new array. I'm iterating over it only once, and then I've got to garbage-collect it later. This could get really expensive if you're dealing with very large source arrays or you're doing this quite often.
How does RxJS save us from this? To show that, I will convert this source into an observable, and I'm going to get my results from a subscription function. Finally we have different arguments because it's an observable.
Now when I run this, you'll see a couple of interesting things. One, I didn't have to change very much about what I was doing other than moving the getting of my reduced result to my subscribe function. The biggest thing is that now you'll see it goes through each -- the filter, the map, and the reduce -- at each step.
I hit zero. Zero gets past my filter, then goes to map, then goes to reduce. The same thing for one, but it doesn't get past my filter. Then I hit two, and it gets past my filter. Then it hits the map. Then it hits the reduce. Three gets filtered out. Four, again all the way through, and five gets filtered out. Finally we get our result.
Here's an animation to show you array, filter, map, reduce. First I filter out my red balls. Then I map to a square, and then I reduce to a stack. You'll notice it creates two intermediary arrays. Those arrays needed to be iterated over each time, and now they'll also have to be garbage-collected.
Now here's an animation showing the exact same thing with arcs observables. You'll notice it takes every item all the way through to the end without creating any intermediary arrays...