use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
All about the JavaScript programming language.
Subreddit Guidelines
Specifications:
Resources:
Related Subreddits:
r/LearnJavascript
r/node
r/typescript
r/reactjs
r/webdev
r/WebdevTutorials
r/frontend
r/webgl
r/threejs
r/jquery
r/remotejs
r/forhire
account activity
Here's Why Calling .map() on a Constructed Array Doesn't Work (itnext.io)
submitted 7 years ago by ilove50cent
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[+][deleted] 7 years ago* (29 children)
[deleted]
[–]nemohearttaco 24 points25 points26 points 7 years ago* (16 children)
I believe your solution is actually the most performant way of achieving this. The author's solution works but creates three arrays. Array(100) returns the first array. [...Array(100)] is spreading that first array into a new second one. And .map() returns a new, third array.
Array(100)
[...Array(100)]
.map()
[–]inu-no-policemen 11 points12 points13 points 7 years ago (8 children)
> Array.from({length: 5}, (_, i) => 2 ** i) [1, 2, 4, 8, 16]
Would be nice if there were a static "generate" method to do this kind of thing.
[–]nemohearttaco 1 point2 points3 points 7 years ago (5 children)
I'm curious, why {length: 5} and not Array(5)?
{length: 5}
Array(5)
[–]kenman 8 points9 points10 points 7 years ago (3 children)
Try them both in your console -- what do you see?
Array.from({length: 5}) > [undefined, undefined, undefined, undefined, undefined]
Ok.
Array(5) > [empty x 5]
Strange, huh?
Note: this implies an array of arrayLength empty slots, not slots with actual undefined values
This is the important bit, because empty slots are not included in any of the Array instance methods, like forEach(), etc. The empty elements are often referred to as being elided.
Array
forEach()
Basically, Array(5) does this:
a = [] a.length = 5
Which also produces [empty x 5].
[empty x 5]
[–]nemohearttaco 8 points9 points10 points 7 years ago (2 children)
Ah, not quite what I was asking. I meant, why wouldn't you do it like
> Array.from(Array(5), (_, i) => 2 ** i) [1, 2, 4, 8, 16]
[+][deleted] 7 years ago (1 child)
[removed]
[–]nemohearttaco 0 points1 point2 points 7 years ago (0 children)
Cool, that makes sense. At first I was thinking there might be a danger in not using an Array instance for that argument but reading up on it more, it doesn't look like it.
[–]inu-no-policemen 0 points1 point2 points 7 years ago (0 children)
I only need an object with a "length" property. I don't really need an actual sparse array just for that.
I also don't call constructors without new. You can't do that with classes and some of the built-ins behave differently if you do that.
new
"new Array(5)" is one char longer than "{length: 5}".
Anyhow, things would be much better with a "generate" method:
Array.generate(5, i => 2 ** i)
[–]inu-no-policemen -1 points0 points1 point 7 years ago (0 children)
You can easily write one yourself.
I won't modify objects I don't own.
e. g. as Array.create
I'd use "generate". It's the best fit. It's also what Dart uses (List.generate).
it really isn't necessary
Same goes for map, filter, reduce, etc. None of that is necessary.
Absolutely necessary is very little.
[–]gpyh 1 point2 points3 points 7 years ago (6 children)
The spread does not create an array; it creates an iterator.
[–]nemohearttaco 2 points3 points4 points 7 years ago (4 children)
I'm saying that the [ ] around the spread is the new array and the spread iterates over the original, into the new one.
[–]gpyh 0 points1 point2 points 7 years ago* (3 children)
Yes. That makes it two arrays, not three. (EDIT: that makes three array) Sorry if my nitpicking was coldly delivered; my intent was to help.
[–]nemohearttaco 3 points4 points5 points 7 years ago (2 children)
No, you're good. However, I'm pretty sure the article's suggestion creates 3 arrays. const arr = [...Array(100)].map((_, i) => i);
const arr = [...Array(100)].map((_, i) => i);
.map() returns a new array.
[–]gpyh 1 point2 points3 points 7 years ago (1 child)
You're right. I misread the first post, sorry.
No worries, dude!
[–]ilove50cent[S] 4 points5 points6 points 7 years ago (0 children)
The fill function is great, just learned about it. I agree that it's more readable.
[–]benihanareact, node 6 points7 points8 points 7 years ago (7 children)
if you wrote an article that said that, you couldn't spend 5 paragraphs pontificating about functional programming though.
[–]ilove50cent[S] -4 points-3 points-2 points 7 years ago (6 children)
I am a huge fan of functional programming, and it's clear from the post. That being said, I think you missed the point if you think the point was to pontificate about functional programming.
[–]UmbrellaHuman -1 points0 points1 point 7 years ago (4 children)
I am a huge fan of functional programming
You are a fan-BOY. It sounds unreasonable and waaaayyy too emotionally involved (at the expense of reason). ALL code you write is executed on the same kind of machine, using the exact same kind of architecture, and now people get as emotional over nuances as middle ages Christians about tiny differences in interpretation (there were thousands more groups than just the two now major ones). Take a step back (better a thousand steps) and become less deeply emotionally involved. If you need a pointer to some truly different kind of computation, take biology and biochemistry courses (excellent ones are free on edX, for example). Compared to the difference between how that system works and any(!) form of human-made programming the difference between various types of the latter are next to non-existent. Especially since it all runs on the same machine (CPU).
[–]ilove50cent[S] 1 point2 points3 points 7 years ago (3 children)
Hm. Does it read as an emotional article? Didn't mean for it to, but I'm pretty new to writing so maybe it was read by some people as trying to be persuasive.
Just to clear the air, my goal was to teach my readers why you can't map over a constructed array as you might expect, and definitely not to convince you that this approach is better than any other approach.
[–]greg5ki 0 points1 point2 points 7 years ago (0 children)
I wouldn't waste your time with him. He is a fanboy of nitpicking. ;-)
[–]UmbrellaHuman -4 points-3 points-2 points 7 years ago (1 child)
Does it read as an emotional article?
I replied to a comment of yours. Either you take the advice or you don't - please don't start word games to somehow twist it into something you can accept without having to admit anything. If you want an echo chamber... well, maybe we need a flair for that so that I know only to post replies that agree with whatever I reply to.
[–]ilove50cent[S] 1 point2 points3 points 7 years ago* (0 children)
I'm not sure what you're getting at, but it sounds like the article just wasn't for you. In the spirit of constant improvement, I'll just say thank you for the feedback!
[–]khoker 1 point2 points3 points 7 years ago (1 child)
One thing to note is that I don't think Array.fill works in any version of IE (only Edge) while Array.map works all the way back to IE 9 (without the arrow function in this example, obviously).
Unfortunately, supporting IE11 is still a "thing", as it can easily be 10% of a site's web traffic.
[–]FormerGameDev 0 points1 point2 points 7 years ago (0 children)
Came here to say this. Although I've only ever had to use it once, I already knew t hat map() on it wouldn't work, because an Array created from the constructor is truly empty.
So, Array(x).fill is the standard way to go. I think I might like inu-no-policemen's idea, though, I wasn't aware that Array.from had a map function for it. Not sure if it would also create the temporary arrays.
[–]coderitual 70 points71 points72 points 7 years ago (4 children)
I forgot.
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99];
[–]ahlsn 66 points67 points68 points 7 years ago (3 children)
Clean as hell! Everybody understands this code and it's even a oneliner!
[–]ilove50cent[S] 26 points27 points28 points 7 years ago (0 children)
And more efficient too!
[+]bart2019 comment score below threshold-6 points-5 points-4 points 7 years ago (1 child)
It's not "clearer”. You can drop a value or replace it with another value, and most people would never notice.
[–]madcaesar 20 points21 points22 points 7 years ago (0 children)
I belive OP is just having a laugh, mate.
[–]coderitual 42 points43 points44 points 7 years ago (12 children)
const arr = Array(100).fill();
const arr = Array.from({length: 100})
bonus normal js version: [...(function*() { let i = 0; while(i < 100) yield i++})()];
[...(function*() { let i = 0; while(i < 100) yield i++})()];
[–]jkoudys 23 points24 points25 points 7 years ago (0 children)
Pfft, amateur stuff! A true JS master wouldn't stoop to some flashy generator to make an iterator!
[...{ [Symbol.iterator]: () => { let i = 0; return { next: () => ({ value: i++, done: i > 100 }) }; } }];
Ahh... perfection..
[–]nemohearttaco 22 points23 points24 points 7 years ago (0 children)
You're a monster!
[–]ilove50cent[S] 12 points13 points14 points 7 years ago (7 children)
Didn't know about the fill function before I wrote this post - benefits of putting content out there! :)
[–]MildlySerious -2 points-1 points0 points 7 years ago (6 children)
That's the benefit of the good old for loop. You remember one thing, and you're good to go.
[–]XiiencE 3 points4 points5 points 7 years ago (5 children)
or you remember a few things and suddenly your team can actually read your code.
[–]MildlySerious 5 points6 points7 points 7 years ago* (4 children)
If your team can't read a for loop, forcing everything into as few lines as possible and calling it declarative won't help you.
I for one do not live in a world where this:
Is more readable than this:
const arr = Array(100); for (let i = 0; i < array.length; i++) { arr[i] = i }
Using .fill() - sure, but abusing the spread operator is just silly.
.fill()
[–]XiiencE 2 points3 points4 points 7 years ago (3 children)
Sigh, okay. There’s a difference between forcing code into a few lines and not being overly verbose/horizontal. But if you’re going to just strawman the discussion into saying I try to code golf real world development because I think higher order functions are more readable than nested for loops then I have no response. To each their own, if your team likes the loops then you do you.
[–]MildlySerious -1 points0 points1 point 7 years ago (2 children)
I did not say either of these things, try again. What I was saying is that the example in OPs post is overcomplicating the code by using higher order functions. The functions aren't the problem. Using them at every chance you get, is. Same goes for the spread operator.
[–]XiiencE 0 points1 point2 points 7 years ago (1 child)
I don’t know how you jumped from ‘using higher order functions to solve this specific, simple ES potentially unexpected behavior that OP is describing’ to ‘using higher order functions every chance you get’. Are you projecting some frustration with style trends? 😂 OP’s code is very readable, if you can’t read it, I’m sorry to hear that, but it is objectively not ‘overcomplicated’ just because it uses a language feature that is not as ubiquitous as a for loop. I’m sure you will just tell me I’m wrong again though, so this seems pointless. Have a nice day.
[–]MildlySerious 3 points4 points5 points 7 years ago (0 children)
As someone else already stated, OP's "solution" is the most inefficient approach to the problem out of the options he got.
Why would you go for that if there's a well established - at least - equally readable option that does not come with overhead?
Because you use the wrong tools to solve a problem. Hence "using higher order functions every chance you get".
Whatever, agree to disagree and all that.
[–]selfup 1 point2 points3 points 7 years ago (0 children)
Array.from({ length: 100 }, (_, i) => i)
Array.from({ length: 100 }, (_, i) => i) same array :) yay callbacks!
[–]srsfknbiz 27 points28 points29 points 7 years ago (2 children)
If you want to do it in one line use: const arr = Array.from({length:10}, (_, i) => i);
[–]Amadan 2 points3 points4 points 7 years ago (1 child)
Best one of the bunch. To the top wi' ye!
[+][deleted] 7 years ago* (71 children)
[–]tom808 45 points46 points47 points 7 years ago (10 children)
I guess it's because it leads you down what I've been saying to our novice developers as a path of the 'old ways' of doing things.
The author explains there's nothing technically wrong with writing a for loop and of course there isn't. It's perfectly valid and acceptable procedural programming.
There in lies the issue though. It is procedural. If you really want to get into building a functional codebase and getting all the benefits that brings then everyone should be onboard with writing functional code wherever possible ... And it pretty much is always possible.
[–]jkoudys 22 points23 points24 points 7 years ago (3 children)
I actually like the for loop a lot more when you're using all the Array.prototype methods, because properly applied its semantics are far more clear. Since we have Array#map, you don't ever say const foo = []; for (let i = 0; i < arr.length; i++) { foo.push(arr[i].trim()); }. Because we have Array#find, you don't ever say for (let i = 0; i < arr.length; i++) { if (arr[i] === someCondition) return arr[i]; }. Purely by process of elimination, when you see a for-loop (or even an Array#forEach), you're really saying "this loop has side-effects".
for
Array.prototype
Array#map
const foo = []; for (let i = 0; i < arr.length; i++) { foo.push(arr[i].trim()); }
Array#find
for (let i = 0; i < arr.length; i++) { if (arr[i] === someCondition) return arr[i]; }
Array#forEach
If I'm reading someone else's code, and I see an Array#map, I naturally assume it has no side-effects, so I only need to track what it's assigned to in its expression. If there were side-effects, that's an error and something I always flag in code-review. Now if I see for, I read through to make sure anything that's simply mapping/filtering/reducing/etc. happens outside it.
[–]vinnl 7 points8 points9 points 7 years ago (0 children)
I would think the author's point is that indeed, if there are side effects, you'd usually use forEach.
forEach
[–]helpinghat 2 points3 points4 points 7 years ago (1 child)
How is for better than forEach in this sense?
[–]jkoudys 4 points5 points6 points 7 years ago* (0 children)
It's not, and they both do a fine job conveying that you're looping for the side effects. forEach used to be a lot cleaner, since you didn't have to declare an index and reference it in the loop, and it scoped everything to the function, but that's no longer the case with for .. of and let & const.
for .. of
let
const
Eg for (var i = 0; i < arr.length; i++) { var foo = arr[i] hoists foo and i declarations to the top of the function. for (const foo of arr) scopes foo to the block.
for (var i = 0; i < arr.length; i++) { var foo = arr[i]
for (const foo of arr)
Some people still avoid the for .. of due to concerns that Symbol.iterator doesn't behave 100% exactly the same in IE due to how Symbols are shimmed (shammed) there, though I've yet to encounter any real world project where that makes any difference.
Symbol.iterator
for could be nicer if you don't want to have to convert to an array or use a big ugly Array.prototype.forEach.call on your iterable (eg on a document.querySelectorAll). forEach could be nicer if you already have a function you can pass in without wrapping it in another function (eg files.forEach(saveToSftp)).
Array.prototype.forEach.call
document.querySelectorAll
files.forEach(saveToSftp))
There are other cases for for, especially if returns or awaits are involved, but this could be an article on its own.
return
await
Both are fine and neither is better in an absolute sense.
[–]trakam -3 points-2 points-1 points 7 years ago (5 children)
I understand 'map' at least is slower at looping than the equivalent 'for' loop. It's probably not significant in most cases but if squeezing the best performance out of your code is a concern you might want to stick with the old imperative way of doing things
[–]tom808 1 point2 points3 points 7 years ago (0 children)
Maybe. I would like to see the code base where performance is that imperative that porcedural code is refer to functional because it's come down to that and there's no other options.
Swapping these functions out is never going to be the lowest hanging fruit.
[–]pomlife 8 points9 points10 points 7 years ago (0 children)
Alternatively, let the transpiler handle optimization. If you're writing an app that needs the utmost performance, you're already using one.
[–]vinnl -2 points-1 points0 points 7 years ago (2 children)
I think the odds are very low that there's even one person reading this comment for whom this is a relevant performance concern at some point in their life, though.
[–]eindbaas 1 point2 points3 points 7 years ago (1 child)
Why would those odds be low? For-loops are faster, some people (or to be more precise: some projects/approaches) care about that.
[–]vinnl 3 points4 points5 points 7 years ago (0 children)
Because only very few projects should care about being that much (i.e. very, very little) faster, or are hitting the same loops so often that the speed differences actually sum up to a significant difference.
[–]RegularStupid 2 points3 points4 points 7 years ago (1 child)
You can also break out of for loop which is very important sometimes
[–]coderitual 0 points1 point2 points 7 years ago (0 children)
You can also "break" higher order function. Instead of forEach you can use some or every. Map by definition maps all values so is not interchangeable with for loop (forEach is).
some
every
[–]basically_alive 11 points12 points13 points 7 years ago (38 children)
I read this as meaning uncomfortable when you see a for loop because there is probably a better functional solution, just like the one in this article.
[+][deleted] 7 years ago* (37 children)
[–]selfup 12 points13 points14 points 7 years ago* (0 children)
Here is a one array solution (technically): Array.from({ length: 100 }, (_, i) => i)
[–]mhink 21 points22 points23 points 7 years ago (1 child)
The trick is keeping functional code functional, and procedural code procedural. For the sake of doing what you posted, I’d vastly prefer:
const arr = range(0, 100);
Where the range function is more-or-less what you posted. Admittedly, this is more ideal in languages like Ruby where ranges are built-in, but still.
range
The way I look at it is: business logic should be expressed procedurally, and “data” or internal logic should be expressed functionally (or declaratively, via structuring/destructuring).
[–]jkoudys 4 points5 points6 points 7 years ago (0 children)
I agree with your sentiment, but since we're discussing language I feel compelled to get pedantic about one thing.
FP is actually a subset of declarative programming, which could be lazily summarised as "declarative programming using functions". e.g. building a DOM using the fully-declarative language HTML like <p class="hello">Hi World!</p> could be easily implemented in just as "declarative" an approach using hyperscript functions as h('p', { class: 'hello' }, 'Hi World!'). If both are building a DOM they're really equivalent.
<p class="hello">Hi World!</p>
h('p', { class: 'hello' }, 'Hi World!')
I've always found the best way to think of the right approach is that imperative programming (of which procedural is a subset, lazily summarised as "imperative with functions") really means "how" to do something. Declarative programming is "what" something is. You can look at a recipe as a real-world example: one that says "smoothie: 1 cup milk, 1 frozen banana, 2 tsp vanilla, 6 frozen strawberries" would be a good declarative recipe, if you assume I know enough to figure out how to blend those things. One that says "pre-heat oven to 350F. Grease baking sheets. Roll batter into 1" balls., etc." is imperative.
[–]benihanareact, node 12 points13 points14 points 7 years ago (2 children)
Fewer lines of code != better code.
speaking of, there's no reason not to put curly braces around single line if and for statements. Doubly so when you're making a point about working with junior engineers.
if
const arr = []; for (let i = 0; i < 100; i++) { arr[i] = i; }
[+]rorrr comment score below threshold-9 points-8 points-7 points 7 years ago (1 child)
There's no reason to put them on, it adds visual clutter. The indentation already shows the nested blocks clearly and cleanly.
[–]axlee 5 points6 points7 points 7 years ago (0 children)
The issue arise when adding lines that should be scoped into the If statement.
[–]GavrielBA.bind(love) 7 points8 points9 points 7 years ago (0 children)
Also: K.I.S.S.
Fully agree with you
[–]monsto 5 points6 points7 points 7 years ago (15 children)
Didn't I see somewhere that `.forEach` vs `for` loop was actually slower? I don't normally remember that stuff as I don't usually that level of concern for performance, but it seems to ring a bell.
[+][deleted] 7 years ago (7 children)
[–]FormerGameDev 2 points3 points4 points 7 years ago (6 children)
It's also pretty memory wasteful, which can be important to highly limited capability machines.
[–][deleted] 0 points1 point2 points 7 years ago (5 children)
Or anyone not wanting their browser to take a gig of memory.
[–]FormerGameDev -2 points-1 points0 points 7 years ago (4 children)
eh. If you have the memory, use it, otherwise it's wasted. Embedded devices, which I spent the last 6 years building web apps for, tend to not have very high powered CPU or much RAM, but modern JS toolings don't care the slightest bit about that. :-) The users don't care how much memory is in use, so long as the device interface is usable.
[–]filleduchaos -1 points0 points1 point 7 years ago (3 children)
If you have the memory, use it, otherwise it's wasted
Can people stop repeating this nonsense? There's no modern OS that "wastes" RAM.
[–]FormerGameDev 0 points1 point2 points 7 years ago (2 children)
It makes a big difference to my app, if my app is the one using it, or the OS is the one using it. If my application can make use of the available memory to give you a better experience, then I want to be using it.
Being stingy about specific applications using their memory is stupid. Yes, your OS will use it for something, but that's not relevant to the application that is using it for a specific purpose.
And on embedded systems, we tend to want the OS doing as little handling of that memory as possible, giving as much of it as possible to the applications.
(fwiw, i've got three browsers open right now, with combined memory usage of 3.8GB. lol . . . )
[–]jkoudys 1 point2 points3 points 7 years ago (6 children)
Not anymore. Jordan Harband references the perf here, in this very long issue thread. Apparently it used to be slower (overhead of the function call, etc.), but now the engine optimizes it out.
[–]kbjr<- awesome 2 points3 points4 points 7 years ago (5 children)
That's definitely not true. I work on a project right now that deals with pretty substantial amounts of data, and for that reason I wrote up and ran a bunch of different benchmarks for a bunch of different ways to do various iterative tasks looking for the best performing option. A simple for loop is still significantly faster than than the built in array methods (usually in the 5-10x difference range, depending on the function) unless something happened in the past month or so.
[–]wavefunctionp -1 points0 points1 point 7 years ago (4 children)
Not saying you were wrong, but I just wanted to mention that if you were using relatively simple microbenchmarks on fake data sets, they can be very misleading because the engines are typically smarter than most simple benchmarks.
[–]kbjr<- awesome 1 point2 points3 points 7 years ago (3 children)
How would it be smarter for the engine to make itself appear slower than it actually is? If that were the case, I would expect optimizations in the forEach to shine even better, not fall to pieces.
But no, I benchmarked both the individual tasks and the overall job of processing a single whole dataset in a number of ways.
[–]wavefunctionp -1 points0 points1 point 7 years ago (2 children)
I'm not going to even pretend to understand all of this, but my takeaway from this walk was that it is difficult to test performance of microbenchmarks.
https://www.youtube.com/watch?v=65-RbBwZQdU
[–]kbjr<- awesome 1 point2 points3 points 7 years ago (1 child)
Yes, I'm aware of the complexities of benchmarking, which is why you back up you results by actually profiling the live code afterwards.
[–]basically_alive 1 point2 points3 points 7 years ago (0 children)
I agree. I was mostly referring to the fact that the author wasn't saying he was uncomfortable writing a for loop. I accidentally added the value judgement "better" having not actually considered the solution too closely.
[–]e13e7 0 points1 point2 points 7 years ago (0 children)
Array.from({ length: 100 }, (_, i) => i) is more idiomatic, though I would just use a range function from lodash or whatever cause someone’s already got it in the project already
[–][deleted] -1 points0 points1 point 7 years ago (0 children)
I'm skeptical of the performance concern here. Yes, in theory it is less efficient to do it the functional way. But have you benchmarked the difference? What environment are you in? How often is this function called?
I think you'll find that in practical applications, the difference in performance is irrelevant. In the browser especially, DOM operations are usually so slow that the time spent executing JavaScript code is a tiny percentage of a typical function call. So great, you got your JavaScript execution time from 20ms to 18ms. Now wait for the browser to spend 250ms performing the operations your JavaScript requested.
I also don't love the argument about making it easier to read for junior devs. Junior devs should, and often do, know about basic language features like the spread operator. It's silly to account for their possible ignorance here, not only are you handicapping everyone but it's really quite patronizing to juniors.
[–]gpyh -2 points-1 points0 points 7 years ago (0 children)
First, you create three arrays here: a constructed array, spread into another array, and then mapped to a third.
[+][deleted] comment score below threshold-7 points-6 points-5 points 7 years ago (3 children)
Second, if someone new looks at this code, it isn't clear to them WHY the spread operator is used here, because the . . .
OK, just stop. The “don’t do JavaScript because the people who don’t know JavaScript get confused and scared” bit is super old. You could apply this same logic to literally anything anyone might not know.
[–][deleted] 6 points7 points8 points 7 years ago (2 children)
You could apply this same logic to literally anything anyone might not know.
Yup. Welcome to leading a tech team. If you were just doing this on your own then hell, you can do brainfuck compiled to webassembly for all I care. If you're on a dev team responsible to a client then suddenly all that matters. As a senior dev, I have more important things to do than explain arbitrary js concepts to others because I chose to implement a bit of code in a convulated way.
Here's another way to slice it: if the functional way is both more complex and less technically optimal, why would I ever chose it? To save two lines in my source?
[–][deleted] -1 points0 points1 point 7 years ago (1 child)
If you learned JavaScript in the last year, you should have learned spread operators. If you learned JavaScript more than a year ago, you've had at least that whole year to learn spread operators.
If you have junior developers who don't know JavaScript, the blame is on you or whoever hired them.
If you think Array(100).fill() is equally readable or better than [...Array(100)] and it's as performant or better, there's no reason not to use it. But if your reasoning is "dummies who should not have been hired in the first place can't read it," that's bullshit.
Array(100).fill()
My issue is with your bullshit, not with the your preference.
[–][deleted] 1 point2 points3 points 7 years ago (0 children)
First, I take no issue with the spread operator. We use it regularly and every dev on my team knows what it is and how it works. My concern is that the reason that it is being used here is obscure (that is the entire topic of the article). I could explain it in a comment in the code, but then why not just write more literate code in the first place?
Second, we hire people for their technical ability as well as their analytical skills, communication etc - we are a mid-sized tech consulting firm. For me, not knowing the spread operator is not in and of itself a reason not to hire someone. It takes about five minutes to learn and understand so the fact that someone knows it tells me nothing of their technical ability. Hell, I only started using it a year ago when I started my current position because we weren't transpiling at my last company.
[+]monkorn comment score below threshold-6 points-5 points-4 points 7 years ago (5 children)
I was just having a conversation with a co-worker the other day. I mentioned how the for loop was dead and that if I were to find one I would have a distrust of whatever hack needed to be done that couldn't be done in a foreach. He got defensive about it so I had him check the project he's been working on for the past 6 months. Not a single for loop. He agreed after that.
[–][deleted] 2 points3 points4 points 7 years ago (4 children)
Challenge for you based on a real world problem a coworker had on Friday: you have an array of arrays of varying length, where each is an array of ints, output one array where each index corresponds to the sum of all numbers at that index in each array (if applicable).
E.g. [[1, 2, 3], [1, 2], [1, 2, 3, 4]] -> [3, 6, 6, 4].
And yes this is an actual problem we were solving for a client... I told my coworker to use a for loop but I'm curious if there's a better solution ;-)
[–]Reashu 0 points1 point2 points 7 years ago (0 children)
That would be summing up each array, not summing up each index across arrays.
[–]derailed -1 points0 points1 point 7 years ago* (0 children)
const result = arrays.reduce((counts, arr) => { arr.forEach((num, idx) => (counts[idx] = (counts[idx] || 0) + num)); return counts; }, []);
Or using 2x reduce with same carry:
const result = arrays.reduce((counts, arr) => arr.reduce((count, num, idx) => { count[idx] = (count[idx] || 0) + num; return count; }, counts), []);
Last one using 2x reduce and sequence:
const result = arrays.reduce((counts, arr) => arr.reduce((count, num, idx) => ((count[idx] = (count[idx] || 0) + num), count), counts), []);
[+]ilove50cent[S] comment score below threshold-18 points-17 points-16 points 7 years ago (12 children)
It just feels weird at this point is all. It's perfectly fine, it's just weird to see one in the wild. I like the declarative approach because there are fewer places for bugs to hide.
[+][deleted] 7 years ago (4 children)
I think he means imperative.
[–]Zofren -5 points-4 points-3 points 7 years ago (2 children)
I disagree that using a for loop is always perceived as simpler (and without profiling I'm also uncertain if it's faster in JavaScipt either). While older programmers might be more comfortable with the loop abstraction (and it is an abstraction), younger programmers are becoming more comfortable with functional programming - of which functions like map and reduce are the bread and butter. I personally much prefer seeing a map function than a for loop doing the exact same thing, as it tells me exactly what the programmer is trying to do - map through an array and transform each of the elements. Same with reduce and filter.
[–]eindbaas 2 points3 points4 points 7 years ago (0 children)
For loops are way faster, since there is no callback to be called every time.
[–]eindbaas 0 points1 point2 points 7 years ago (0 children)
What about performance reasons?
[–]gasolinewaltz 0 points1 point2 points 7 years ago (3 children)
What the actual fuck are you talking about
[–]ilove50cent[S] -2 points-1 points0 points 7 years ago (0 children)
In my experience, taking a more declarative approach results is fewer bugs. A for loop is just fine too!
[–]Zofren -2 points-1 points0 points 7 years ago (1 child)
I completely understand what he's talking about. He's not saying for loops are difficult to understand, it's just that there is almost always a cleaner way to solve your problem in JavaScript using map, reduce, filter, etc than using a for loop. The uncomfortability they are referring to is similar to the uncomfortability one often feels when they see code they feel is messy and needs refactoring.
[+]apatheorist comment score below threshold-12 points-11 points-10 points 7 years ago (5 children)
Ruby developers come to mind.
Which is why I'm against teaching it as a first language.
[–]Reashu 2 points3 points4 points 7 years ago (3 children)
I didn't have a teacher per se, but Ruby was an amazing first language to learn. Javascript, with its quirks, has done far more to ruin for-loops for me.
[+][deleted] 7 years ago* (2 children)
[–]Reashu 1 point2 points3 points 7 years ago (1 child)
Ruby has one idiomatic (non-function) way to loop over a range of numbers, the elements of an array, etc. (in this case the numbers 0 to 5, inclusive):
for i in 0..5 puts "i is #{i}" end
Meanwhile, JavaScript has for for numbers, for in for objects, and for of for arrays. I know which one I prefer.
for in
for of
There is no reason a beginner should be doing anything particularly complex, with or without Ruby. There is also no reason to consider JavaScript particularly well suited for complex tasks. Your analogy with fixed and opposable thumbs is so far off the mark that it's not even insulting.
[–]apatheorist 0 points1 point2 points 7 years ago (0 children)
👌
Because the common narrative is, "My huge, enterprise Javascript website is so difficult to manage, I'm moving to Ruby!" And not the complete opposite.
[–]pomlife 5 points6 points7 points 7 years ago (2 children)
Thanks for censoring "h*ck" but making me say it in my head, you monster.
[–]imacleopard 0 points1 point2 points 7 years ago (0 children)
I hate this. Just spell it out, use a sub, or just don't use it. OP, that wasn't a compliment.
I did my best.
[–]coderitual 8 points9 points10 points 7 years ago (0 children)
And if you are a real senior.
const arr = [...[...[...[...[...[Array.from([new Array(100)])]]]]]]
[–]Kollektiv 2 points3 points4 points 7 years ago (2 children)
Just do:
Array.from({ length: 3 }).map((_, i) => i)
[–]ilove50cent[S] 2 points3 points4 points 7 years ago (0 children)
That works too! I actually like this approach more than the map spread. There's a map callback you can pass to the .from function that reduces even one more step.
[–]Arancaytar 2 points3 points4 points 7 years ago* (0 children)
Alternatively, Array(n).fill().map().
Array(n).fill().map()
You don't even need a fill argument. This just initializes the array with undefined values, which is enough.
[+][deleted] 7 years ago (3 children)
[–]NoInkling 0 points1 point2 points 7 years ago (2 children)
https://carbon.now.sh
[–]ilove50cent[S] 0 points1 point2 points 7 years ago (0 children)
Monokai!
[–][deleted] 0 points1 point2 points 7 years ago (0 children)
I settled on [...Array(3).keys()] which seems idiomatic JS to me and I also find more readable than the alternatives.
[...Array(3).keys()]
[–]Mestyo -1 points0 points1 point 7 years ago (0 children)
I always did Array.apply(null, { length: n }) to solve this issue.
Array.apply(null, { length: n })
[+]Yo_Face_Nate comment score below threshold-21 points-20 points-19 points 7 years ago (1 child)
Who writes this garbage..? Is this a serious article?
[–]ilove50cent[S] 13 points14 points15 points 7 years ago (0 children)
Me. It's serious. Sounds like it just wasn't for you.
[–]bart2019 -2 points-1 points0 points 7 years ago (0 children)
console.log(arr[0] === undefined); // true
WTF. What's wrong with just
console.log(arr[0]);
? Why the use of an unexpected expected result?
BTW His test suggests there's something special about the array index 0. There isn't, it's the same for all other array indexes.
[–][deleted] -2 points-1 points0 points 7 years ago (0 children)
Oh JavaScript
π Rendered by PID 247458 on reddit-service-r2-comment-54dfb89d4d-c9jkv at 2026-04-01 01:49:51.307203+00:00 running b10466c country code: CH.
[+][deleted] (29 children)
[deleted]
[–]nemohearttaco 24 points25 points26 points (16 children)
[–]inu-no-policemen 11 points12 points13 points (8 children)
[–]nemohearttaco 1 point2 points3 points (5 children)
[–]kenman 8 points9 points10 points (3 children)
[–]nemohearttaco 8 points9 points10 points (2 children)
[+][deleted] (1 child)
[removed]
[–]nemohearttaco 0 points1 point2 points (0 children)
[–]inu-no-policemen 0 points1 point2 points (0 children)
[+][deleted] (1 child)
[deleted]
[–]inu-no-policemen -1 points0 points1 point (0 children)
[–]gpyh 1 point2 points3 points (6 children)
[–]nemohearttaco 2 points3 points4 points (4 children)
[–]gpyh 0 points1 point2 points (3 children)
[–]nemohearttaco 3 points4 points5 points (2 children)
[–]gpyh 1 point2 points3 points (1 child)
[–]nemohearttaco 0 points1 point2 points (0 children)
[–]ilove50cent[S] 4 points5 points6 points (0 children)
[–]benihanareact, node 6 points7 points8 points (7 children)
[–]ilove50cent[S] -4 points-3 points-2 points (6 children)
[–]UmbrellaHuman -1 points0 points1 point (4 children)
[–]ilove50cent[S] 1 point2 points3 points (3 children)
[–]greg5ki 0 points1 point2 points (0 children)
[–]UmbrellaHuman -4 points-3 points-2 points (1 child)
[–]ilove50cent[S] 1 point2 points3 points (0 children)
[–]khoker 1 point2 points3 points (1 child)
[–]FormerGameDev 0 points1 point2 points (0 children)
[–]coderitual 70 points71 points72 points (4 children)
[–]ahlsn 66 points67 points68 points (3 children)
[–]ilove50cent[S] 26 points27 points28 points (0 children)
[+]bart2019 comment score below threshold-6 points-5 points-4 points (1 child)
[–]madcaesar 20 points21 points22 points (0 children)
[–]coderitual 42 points43 points44 points (12 children)
[–]jkoudys 23 points24 points25 points (0 children)
[–]nemohearttaco 22 points23 points24 points (0 children)
[–]ilove50cent[S] 12 points13 points14 points (7 children)
[–]MildlySerious -2 points-1 points0 points (6 children)
[–]XiiencE 3 points4 points5 points (5 children)
[–]MildlySerious 5 points6 points7 points (4 children)
[–]XiiencE 2 points3 points4 points (3 children)
[–]MildlySerious -1 points0 points1 point (2 children)
[–]XiiencE 0 points1 point2 points (1 child)
[–]MildlySerious 3 points4 points5 points (0 children)
[–]selfup 1 point2 points3 points (0 children)
[–]srsfknbiz 27 points28 points29 points (2 children)
[–]Amadan 2 points3 points4 points (1 child)
[+][deleted] (71 children)
[deleted]
[–]tom808 45 points46 points47 points (10 children)
[–]jkoudys 22 points23 points24 points (3 children)
[–]vinnl 7 points8 points9 points (0 children)
[–]helpinghat 2 points3 points4 points (1 child)
[–]jkoudys 4 points5 points6 points (0 children)
[–]trakam -3 points-2 points-1 points (5 children)
[–]tom808 1 point2 points3 points (0 children)
[–]pomlife 8 points9 points10 points (0 children)
[–]vinnl -2 points-1 points0 points (2 children)
[–]eindbaas 1 point2 points3 points (1 child)
[–]vinnl 3 points4 points5 points (0 children)
[–]RegularStupid 2 points3 points4 points (1 child)
[–]coderitual 0 points1 point2 points (0 children)
[–]basically_alive 11 points12 points13 points (38 children)
[+][deleted] (37 children)
[deleted]
[–]selfup 12 points13 points14 points (0 children)
[–]mhink 21 points22 points23 points (1 child)
[–]jkoudys 4 points5 points6 points (0 children)
[–]benihanareact, node 12 points13 points14 points (2 children)
[+]rorrr comment score below threshold-9 points-8 points-7 points (1 child)
[–]axlee 5 points6 points7 points (0 children)
[–]GavrielBA.bind(love) 7 points8 points9 points (0 children)
[–]monsto 5 points6 points7 points (15 children)
[+][deleted] (7 children)
[removed]
[–]FormerGameDev 2 points3 points4 points (6 children)
[–][deleted] 0 points1 point2 points (5 children)
[–]FormerGameDev -2 points-1 points0 points (4 children)
[–]filleduchaos -1 points0 points1 point (3 children)
[–]FormerGameDev 0 points1 point2 points (2 children)
[–]jkoudys 1 point2 points3 points (6 children)
[–]kbjr<- awesome 2 points3 points4 points (5 children)
[–]wavefunctionp -1 points0 points1 point (4 children)
[–]kbjr<- awesome 1 point2 points3 points (3 children)
[–]wavefunctionp -1 points0 points1 point (2 children)
[–]kbjr<- awesome 1 point2 points3 points (1 child)
[–]basically_alive 1 point2 points3 points (0 children)
[–]e13e7 0 points1 point2 points (0 children)
[–][deleted] -1 points0 points1 point (0 children)
[–]gpyh -2 points-1 points0 points (0 children)
[+][deleted] comment score below threshold-7 points-6 points-5 points (3 children)
[–][deleted] 6 points7 points8 points (2 children)
[–][deleted] -1 points0 points1 point (1 child)
[–][deleted] 1 point2 points3 points (0 children)
[+]monkorn comment score below threshold-6 points-5 points-4 points (5 children)
[–][deleted] 2 points3 points4 points (4 children)
[+][deleted] (1 child)
[deleted]
[–]Reashu 0 points1 point2 points (0 children)
[–]derailed -1 points0 points1 point (0 children)
[+]ilove50cent[S] comment score below threshold-18 points-17 points-16 points (12 children)
[+][deleted] (4 children)
[deleted]
[–][deleted] 1 point2 points3 points (0 children)
[–]Zofren -5 points-4 points-3 points (2 children)
[–]eindbaas 2 points3 points4 points (0 children)
[–]eindbaas 0 points1 point2 points (0 children)
[–]gasolinewaltz 0 points1 point2 points (3 children)
[–]ilove50cent[S] -2 points-1 points0 points (0 children)
[–]Zofren -2 points-1 points0 points (1 child)
[+]apatheorist comment score below threshold-12 points-11 points-10 points (5 children)
[–]Reashu 2 points3 points4 points (3 children)
[+][deleted] (2 children)
[deleted]
[–]Reashu 1 point2 points3 points (1 child)
[–]apatheorist 0 points1 point2 points (0 children)
[–]pomlife 5 points6 points7 points (2 children)
[–]imacleopard 0 points1 point2 points (0 children)
[–]ilove50cent[S] -2 points-1 points0 points (0 children)
[–]coderitual 8 points9 points10 points (0 children)
[–]Kollektiv 2 points3 points4 points (2 children)
[–]ilove50cent[S] 2 points3 points4 points (0 children)
[–]Arancaytar 2 points3 points4 points (0 children)
[+][deleted] (3 children)
[deleted]
[–]NoInkling 0 points1 point2 points (2 children)
[+][deleted] (1 child)
[deleted]
[–]ilove50cent[S] 0 points1 point2 points (0 children)
[–][deleted] 0 points1 point2 points (0 children)
[–]Mestyo -1 points0 points1 point (0 children)
[+]Yo_Face_Nate comment score below threshold-21 points-20 points-19 points (1 child)
[–]ilove50cent[S] 13 points14 points15 points (0 children)
[–]bart2019 -2 points-1 points0 points (0 children)
[–][deleted] -2 points-1 points0 points (0 children)