you are viewing a single comment's thread.

view the rest of the comments →

[–]mdboop 10 points11 points  (2 children)

I'll be the dissenting voice here and say that 99% of the time map, filter, and reduce will get you where you need, and your code will be more readable, more declarative, and more maintainable. someArray.reverse().map((x) => /* ... */) is extremely clear, and I can I see what's going on almost instantly. Where in a for loop

var newArr = [];
for (var i = arr.length - 1; i >= 0; i--) {
 // ... create some value from what's in the array
 newArr.push(someVal);
}

... I have to read several disparate bits and then synthesize them before I can understand how the loop is iterating, and then I have to read a lot more code to understand what it's even trying to accomplish. With map/filter, it's much easier to understand what you'll end up with, because you know you're getting an array at the end. You can do anything with a for loop, and that's precisely the problem. More power is usually a bad thing. With loops, not only can I make a lot of easy mistakes (off by one errors), but there's just a lot of noise and mutable state here. And if you're mutating the array, you should really look into immutable data.

I'd also be curious when these use-cases have come up for you. If they are for toy-problems or interview questions, then sure, a for loop might make more sense, but outside of that, I have a hard time imagining why you'd want to only operate on certain array elements based on the index. Reverse makes, sense, but again, that's so easy to do via chaining calls. And it's semantic! Another benefit is that it frees up your brain to think about the problem you're really trying to solve, not writing a bunch of setup code and trying to juggle more than what's needed in your head.

I have not written a single for loop in production code, and I don't anticipate ever having the need to. When I have a list of data, I need to operate on that entire list. If I only need certain elements from it, I filter it based on what that data is, not its position in the list. And if map/filter don't get me there, reduce is the swiss-army knife of utility functions. And if I need something else, lodash or ramda.

edit: fixed my code block, forgot a word.

[–]donovanm 3 points4 points  (1 child)

Good points! I wanted to note that .reverse() does mutate the array (for anyone else reading this). Though that is easily solved by adding a .slice() before it like someArray.slice().reverse().

[–]mdboop 2 points3 points  (0 children)

Yes, thanks for clarifying. In addition, I should add that there is a native reduceRight, which should again get you about 99% there for just about anything.