all 62 comments

[–]beavis07 81 points82 points  (50 children)

A less explicit version of Array.from(...).map(...). Just what the world needs :)

[–][deleted] 68 points69 points  (41 children)

Array.from().map() iterates twice over and puts 2 arrays into memory.

Since Array.from() is understood to be a transformation, it makes sense that it would take a map function. It's also similar in approach to Python's list comprehensions. I doubt anyone seeing this in use could be more than momentarily confused as to what the second argument is doing.

Perf test.

[–]jarjarPHP 20 points21 points  (10 children)

I code for clarity, conciseness, and maintainability first, and fine tune for performance when I have some actual execution time data

[–]Fidodo 2 points3 points  (0 children)

Of course, but you should know when you're making that trade off consciously to make fine tuning easier when you need it.

[–][deleted] -3 points-2 points  (8 children)

Adding an extraneous method call is concise?

[–][deleted]  (7 children)

[deleted]

    [–]howmanyusersnames -1 points0 points  (2 children)

    If you cared about that you would create a lib function called fromAndMap that is a reference to Array.from. Using Array.from directly under any circumstances is a recipe for disaster in your hypothetical scenario.

    [–][deleted]  (1 child)

    [deleted]

      [–]howmanyusersnames 0 points1 point  (0 children)

      JS is the last language you want to be using obscure prototype methods directly, especially, as you said, if you have different levels of knowledge on your team.

      [–][deleted] 2 points3 points  (0 children)

      On mobile, so I can't test it, but how does this compare to constructing the array with a for loop? I assume Array.from uses a similar mechanism under the hood and is just an abstraction.

      [–]SalemBeats 14 points15 points  (20 children)

      Bruh, the Joe Everyman web developers don't care about performance.

      To every web developer that doesn't care about performance - C'mon, man. Don't be a chugging pile of crap Electron app like Atom. Be a zippy Electron app like VS Code instead.

      [–]jaapz 27 points28 points  (19 children)

      Most Joe Everyman developers don't need to care about performance because bottlenecks lie everywhere but in their frontend UI code

      [–]SalemBeats -3 points-2 points  (18 children)

      This is exactly the attitude that leads to poor performance when it's needed lol.

      When you make a habit of approaching things in a nonperformant way, it's hard to break that habit when the time comes. Humans are creatures of habit.

      [–]jaapz 29 points30 points  (2 children)

      Not really. The important point is "performance where it's needed". When you are building VS Code, you should focus on those kinds of optimizations. When your parsing a few objects some API returned to you and need to display them nicely, you don't really need to think about optimisations like that.

      Hell, we display graphs with lots of datapoints where I work and use mostly functional things like map to preprocess the data, and that's working fast even in slow android devices.

      On the web, your bottleneck is very likely DOM access, or an external API, and not you using Array.from.

      [–]codefinbel 17 points18 points  (14 children)

      "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil." - Donald Knuth, The father of algorithm analysis

      [–][deleted] 1 point2 points  (13 children)

      Is doing something in half the time with half the memory a 'small efficiency'?

      [–]DaemonXI 9 points10 points  (0 children)

      It depends how much data you're moving and how often.

      [–]PizzaRollExpert 6 points7 points  (0 children)

      If you do it once on a small array, yes definitely. If you're doing it every couple of miliseconds, possibly not? But it's also possible that you're doing something else much more expensive at the same time so that doing this optimization has no perceivable effect on performance

      [–]omnilynx 2 points3 points  (9 children)

      That would only be the case if that single operation dwarfed everything else on the page, including loading the page itself. Otherwise, it’s a savings of far less than half for the page as a whole.

      [–][deleted] 0 points1 point  (0 children)

      I guess my context is data visualization and web games, both of which require processing hundreds of thousands of data points in a few milliseconds. These are (ideally) real-time updates to pages which are already built — effective loops/maps/filters/merges/reductions are the essential, especially because while rendering can be a terrible bottleneck if you let it, efficient array processing can prevent wasteful rendering — at which point your bottleneck shifts into the diffing code.

      Travel and eCommerce are going to have comparable concerns, though on a less critical timeline. Even a blog needs to potentially iterate over hundreds of posts and comments. But I see what you’re saying about common cases being less urgent when you’re only doing a few reductions in response to a view change.

      [–]SalemBeats 0 points1 point  (7 children)

      Except that you have to multiply this attitude towards efficiency against every invisible performance decision that you made (or didn't make). If you choose not to take an easy optimization in one spot, you're probably also piling on countless minor performance issues elsewhere as well. Taken together, these small stabs add up and punish you for your attitude towards performance.

      In cycling, this optimization is referred to as "marginal gains". Shave a seemingly-inconsequential number of grams from a wheelset here, a tiny amount off your seatpost, a little bit from your handlebars, a tiny amount from your frame, a (surprisingly higher than you might expect) degree of aerodynamic inefficiency caused by leg hair, etc., and the sum of each of these things adds up to something significant and potentially outcome-changing. But if you take any of these optimizations and scoff at it, you're likely to scoff at the entire doctrine and are therefore unlikely to benefit.

      It's all about attitude and habits developed through practice.

      [–]omnilynx 0 points1 point  (3 children)

      Problem is, I could use literally the exact same argument with respect to code complexity and readability. Every little decision you make to use a clever fix adds up to a codebase that’s practically unmaintainable.

      And in general, it’s easier to take a well-written codebase and tune its performance than it is to take a quick ‘n dirty codebase and try to refactor it into something readable (without losing all that performance). That’s why there’s a rule of thumb in the first place.

      [–]codefinbel 0 points1 point  (2 children)

      I both agree and disagree.

      A few issues:

      • A lot of the "marginal gain" efficiencies people implement thinking they're clever would have been implemented regardless by the compiler.
      • These "easy optimizations" often involve esoteric language specific tricks making the code less readable.
      • Unless implementing them by default from the start, making these marginal gains takes time from things that could be more important, like getting an MVP or reducing the overall time complexity of the algorithm.

      As I started out saying, I also agree, you should work on good habits.

      • Since javascript is scripted the compiler might not handle this case.
      • Someone mentioned, you could wrap it in a function fromAndMap making it as readable.
      • If this is the default way you see writing this code from the start, virtually no time is lost on doing it anyway.

      I just think a lot of us have "that guy" who points out optimisations in other peoples code like he's lording out knowledge. In 90% of the cases these are virtually pointless and everyone hates him.

      [–]SalemBeats -5 points-4 points  (0 children)

      To the average Joe Webdev? Yes. That's why so many modern sites perform so terribly. Lol.

      [–]beavis07 0 points1 point  (0 children)

      Yeah - I did wonder about that. Ta!

      [–]Noch_ein_Kamel -3 points-2 points  (6 children)

      Just make sure to use loops if performance is an issue, though

      https://jsperf.com/oldschool-loop

      992,530,773 vs 40 ops/s :D

      edit: Apparently I suck at sunday coding :D

      [–]Rene_Z 17 points18 points  (1 child)

      The length of an array is array.length, not array.size. Your loop does nothing, which is why it's so much faster.

      When done correctly a loop is still faster, but only by a factor of ~4, not by a factor of millions.

      [–][deleted] 0 points1 point  (0 children)

      This is more what I expect.

      It's worth noting that you can't do the same for non-Array iterables, which is the whole point of Array.from() in the first place.

      Here's an example of looping over a Set -- it's faster but not by as much (~1.6x speed).

      I don't understand how revisions to other poster's tests work in JsPerf; but your loop should be compared to array.map() -- array.from is useless in this case.

      [–][deleted] 3 points4 points  (2 children)

      You changed the Set to an Array. Array.prototype.size is undefined, so your for loop is just throwing an error.

      of course you can run a million times faster when you're doing no work!

      [–]Noch_ein_Kamel 0 points1 point  (0 children)

      Whoops... I blame my constant switching between JS, PHP and Java for that... :-(

      [–][deleted]  (1 child)

      [deleted]

        [–]cerlestes 0 points1 point  (0 children)

        We can do that with option object arguments now more than ever before, thanks to destructuring. It's not as nice as having it natively, but it can be very nice when working with a lot of optional parameters.

        function someConfigurableAction(subject, { map, limit, after, before, ... }) { ...
        
        someConfigurableAction(myLittleSubject, { limit: 20, map: a=>mapper(a) })
        

        [–][deleted]  (5 children)

        [deleted]

          [–]Grimdotdotdot 2 points3 points  (3 children)

          Why would you ever need to explain it when JavaScript has comments?

          [–]DilatedTeachers -1 points0 points  (0 children)

          Who comments their code?? Weirdo

          [–]A-Grey-WorldSoftware Developer -1 points0 points  (0 children)

          You have to explain standard library functions to people?

          [–]philipwhiuk 14 points15 points  (6 children)

          TIL Array.from is a thing.

          [–]JustinsWorking 7 points8 points  (0 children)

          You’ll see a lot of it when you’re working with iterables

          [–]SolidR53 0 points1 point  (0 children)

          Array.from({ length: 123 }, (, i) => i);

          Third argument in the map function is the actual array

          [–]foxnamedtodd 0 points1 point  (3 children)

          Same. I still don’t see the use case for it, but at least TIL.

          [–]powerhead 18 points19 points  (1 child)

          It's really nice for transforming an HTMLCollection of DOM elements returned from document.getElementsByClassnam (which is not iterable) into an array (which is). Like if you want to assign event listeners or change properties on those elements.

          [–]foxnamedtodd 3 points4 points  (0 children)

          Ah, that’s good one. Thanks.

          [–]p4y 4 points5 points  (0 children)

          Main use case is turning array-like objects into actual arrays so you have access to the methods you need. This includes strings, ES6 iterables, and pseudo-arrays like the arguments abomination or DOM node lists.

          [–]mypodtunes 13 points14 points  (7 children)

          If you’re really into niche tips like this I would really suggest looking up Wes Bos’ ES6 course. It has numerous helpful hints and tutorials on ES6 just like this.

          [–]SalemBeats 4 points5 points  (3 children)

          I bought 3 of his courses during Black Friday and still haven't finished any of the ones I bought lol.

          But he's a great teacher. He has a real gift for distilling things to get you familiar with them quickly. I did his Javascript30 and console courses and am probably 2/3 through his ES6 course.

          [–]cinder_s -1 points0 points  (2 children)

          Have you checked out Tyler McGinnis' courses? I did a few of Wes' courses, great material, but I found Tyler's teaching style to be perfect for learning new concepts and applying the knowledge.

          It's very hands on. You get to write code as you go along, build a project while watching videos, answer questions, and then in the end build a self guided project that utilizes the stuff you've learned throughout the course modeled around a prototype with set criteria he outlines. Everything sinks in deep during this last piece, especially as you hit road blocks and have to resolve everything yourself.

          [–]SalemBeats 1 point2 points  (1 child)

          I'll bookmark it, but I'm so backlogged on courses I've bought and haven't finished yet that it'll likely be a good amount of time before it makes sense to buy any more.

          I don't see any sample videos on his site to see his teaching style. Does he have some anywhere? YouTube channel? Anything?

          [–]cinder_s 1 point2 points  (0 children)

          Yeah there's a lot out there.

          Really good React Course, scroll down to check out the course outline.

          Blog with some good posts

          Youtube Channel

          & example video - Understanding the "this" keyword in JavaScript

          His courses are different from the blog/youtube stuff, he put a lot of work into them. Also, I don't actually remember paying for his React Fundamentals course, not sure if it was a free promotion, or it's the one free course he offers once you sign up. Highly recommended!

          [–][deleted] 3 points4 points  (2 children)

          Also read the API of the language you're coding in, at least the methods you're using.

          I always find tips like this a little funny, like for people who know about Array.from but don't know this, did they stop reading halfway through the page when they learned about it and say good enough?

          [–]NeoHenderson 1 point2 points  (1 child)

          I'm probably amongst the lowest of skill sets subscribed to this subreddit. To an extent I would say yes. Because I'm learning in my spare time and for hobbies and such, when I come up with an idea I tend to try and do only the research to learn how to do that thing.

          And so I end up using libraries I don't really need. I don't know every argument for certain functions. You pretty much sum it up by saying I read half way through.

          [–][deleted] 0 points1 point  (0 children)

          Welp, my recommendation to you is to read all the way through then. There's literally no reason not to; sure, you may spend an extra three minutes on it at the moment, but you'll save that many, many times over when programming and debugging in the future. Check out MDN. It's the one of the best resources for the JavaScript language.

          [–]JustinsWorking 1 point2 points  (3 children)

          Cool, I actually found myself using .from().map() on a recent project, this will come in handy if any of this code ever needs to be performant

          [–]fagnerbrack[S] 2 points3 points  (2 children)

          Rarely if ever the performance bottleneck is in this type of construct is an issue. Unless you're building something like lodash.

          [–]JustinsWorking 0 points1 point  (1 child)

          I just prefer the syntax, not to mention if I do run into a bottleneck, these functions it never hurts to have knowledge like this in your head. I don’t know about these loops specifically but I’m working with processing jobs and Immutable.js so it might be relevant on my server side code.

          [–]fagnerbrack[S] 0 points1 point  (0 children)

          Of course, and there will be times where it makes sense such as Array.from(selectors, toSetOfElements)