Video není dostupné.
OmlouvĂĄme se.

Is JavaScript Spread a Performance Killer? Quick Fix

SdĂ­let
VloĆŸit
  • čas pƙidĂĄn 18. 08. 2024
  • (I said destructuring when what I'm really doing is spreading, same performance impacts apply regardless of the terminology.)
    Using spreading with Array.reduce is a powerful pattern, but it can also be a performance killer. Let's learn what causes the performance issues and how to get around it while still keeping the same powerful functionality.
    Code: github.com/jhe...
    👉 What's my theme? Night Wolf [black]
    👉 What's that font? Operator Mono
    👉 I'm a host on the React Round Up podcast: devchat.tv/pod...
    👉 Don't forget to subscribe to this channel for more updates: bit.ly/2E7drfJ
    👉 Discord server signup: / discord
    00:00 Introduction
    00:35 Object speading performance
    05:45 Array speading performance
    08:06 Why do we do this?
    09:10 Outroduction
    Thank you for watching this video, click the "SUBSCRIBE" button to stay connected with this channel.
    #javascript #quickFix

Komentáƙe • 189

  • @lynn_phoenix
    @lynn_phoenix Pƙed 2 lety +21

    For a real world improvement, this was the difference of a search endpoint taking 1100ms vs 200ms. The original developer preferred DX with expressive code over user affecting performance and it caused Core Web Vital issues.

  • @ZakiWasik
    @ZakiWasik Pƙed 2 lety +39

    This is really interesting. I've been doing spread destructuring simply out of habits acquired from using Redux. But I guess I have to rethink that when using reduce.

  • @ddoice
    @ddoice Pƙed 2 lety +10

    This is why ended up using ramda, it allows you to keep the functional syntax with great performance.
    On a brute force code I needed all the permutations of combinations of words extracted from paragraphs (near 1.5M), the code using reduce will take 4 hours to calculate all, with ramda was 5 secs.

  • @HeinekenLasse
    @HeinekenLasse Pƙed 2 lety +36

    Wow I always thought that background was real haha

    • @jherr
      @jherr  Pƙed 2 lety +25

      It is actually my office. I just use a plate that I shot at the day in summer, and so now I can use it in the dark of fall. ;)

    • @harvenius
      @harvenius Pƙed 2 lety +4

      @@jherr damn that is an incredibly nice environment for an office!

  • @floofynuggets
    @floofynuggets Pƙed 2 lety +17

    This is a great tip, Jack! I've also implemented this in performance-sensitive situations. However, I don't always apply this advice because of the no-param-reassign eslint rule which I usually have enabled in my projects. This rule helps avoid mutating object references passed into a function.
    I think I'd add one point to Jack's video here: this performance-boosting trick has no downsides _because_ the lookup is initialized with {}, and not an existing object reference. If you're in this situation, only _then_ is it permissible to apply this approach and ignore the rule.
    Cheers!

    • @jherr
      @jherr  Pƙed 2 lety +5

      Honestly, I never even think of initializing reduce with an existing reference.

    • @floofynuggets
      @floofynuggets Pƙed 2 lety

      @@jherr I don't blame ya! Neither do I. The lint rule just discourages me from consistently applying this tip and I thought I'd help explain it. Thanks again for your work making videos Jack.

  • @henrmota
    @henrmota Pƙed 10 měsĂ­ci +4

    Jack, I think it would be interesting to make a video on how to measure the performance of functions and how to measure that performance. Thanks for your videos.

  • @mammothoff
    @mammothoff Pƙed 2 lety +5

    I always destructture with spread, but now I'll think twice before using spread, thanks đŸ‘đŸ»

  • @codezero6023
    @codezero6023 Pƙed 2 lety +11

    Yes, I have gotten burned using an assign function in a reduce. The spread operator may seem more functional, but “mutating” the accumulator by setting the key is much more efficient.

  • @Kay8B
    @Kay8B Pƙed 2 lety +3

    This is amazing, More efficiency tips like this would be awesome short videos to share with friends.

  • @AbdelhameedG
    @AbdelhameedG Pƙed 2 lety +3

    Thanks Jack, That was enlighting, Would love to see more videos about performance from you.

  • @cwinter90
    @cwinter90 Pƙed 2 lety +15

    Didn't realize the performance was that bad between them lol. I believe I've always done the good version but that was more by luck than thinking about performance I think đŸ€Ł

  • @purswanitarun
    @purswanitarun Pƙed 2 lety +1

    Your voice and way of explaining makes me want to get up early and always keep learning.
    Thank you :)

  • @sagarreddy7461
    @sagarreddy7461 Pƙed 2 lety +2

    Awesome content jack, thanks. Waiting for your js objects details series

  • @mauriciabad
    @mauriciabad Pƙed 2 lety +40

    I would have done this: Object.fromEntries(people.map(person => [ person.id, person ]))
    I don't know how efficient it is, but it's very readable.

    • @jherr
      @jherr  Pƙed 2 lety +3

      That's a good one, and it should be very efficient.

    • @AbdelhameedG
      @AbdelhameedG Pƙed 2 lety

      Nice idea

  • @JulioDx3480
    @JulioDx3480 Pƙed 2 lety +1

    I had no idea about this performance hit with destructuring. Thanks for sharing.

  • @DanielTateNZ
    @DanielTateNZ Pƙed 2 lety +1

    This answers the questions I had on your other reduce video. Thanks!

  • @drewbird87
    @drewbird87 Pƙed 2 lety +3

    I'm still calculating the amount of times I've done this using ...spread . 😳 Thanks Jack đŸ‘đŸŒđŸ‘đŸŒ

  • @ShaharHarshuv
    @ShaharHarshuv Pƙed rokem +6

    I think mutating the object you're creating still abides functional programming principles since you're not mutating the function arguments, so the function is still pure. I think it's ok that the reducer's callback is not pure since it's used once and in place

  • @mohammadmahdifarnia5358
    @mohammadmahdifarnia5358 Pƙed rokem +1

    Immutability kills performance & blows up memory.
    react-table had this issue (primegen has a video on this)
    Great video👍

  • @Weagle1337
    @Weagle1337 Pƙed rokem +1

    Thank you Jack, I enjoyed this video at 1:00 AM eating an instant ramen

  • @collenzaligway4458
    @collenzaligway4458 Pƙed 2 lety +1

    I love you content. Thanks for sharing your knowledge. Will share your video to my colleague so you can get more subscriber.

  • @Shahbaaz.28
    @Shahbaaz.28 Pƙed rokem +1

    Now I finally got something new on you tube Thank man

  • @Sashankyt
    @Sashankyt Pƙed 2 lety +1

    I would have never done that spread but it was insightful. Thank You.

  • @jrs_devs
    @jrs_devs Pƙed 2 lety

    Perfecto!, just corrected a couple of pieces of code with this smart fix. Thank you Jack!

  • @PeerReynders
    @PeerReynders Pƙed 2 lety +20

    Nitpick.
    Technically this isn't about destructuring assignment but the spread syntax being used to *create* object instances. Destructuring uses the rest syntax (which gathers properties rather than spreads) which looks exactly like the spread syntax. The spread syntax expresses is the opposite of the rest syntax used in destructuring.

    • @jherr
      @jherr  Pƙed 2 lety +8

      You are correct and fixed in the title and description.

  • @stephanekiss
    @stephanekiss Pƙed rokem +2

    A spread inside a reduce is going to be a square complexity, not cube. There is one loop in the spread operator that has to copy every property of the lookup object into a new object, and the other is the reduce. Two nested loops = square.

  • @mostafaabobakr
    @mostafaabobakr Pƙed 2 lety +2

    THANK YOU
    applied this immediately

  • @adamlerman4173
    @adamlerman4173 Pƙed 2 lety +1

    Thanks as always for a great video Jack!

  • @Yutaro-Yoshii
    @Yutaro-Yoshii Pƙed rokem +1

    If you don't plan to consume the output right away, for loop is also a great option.
    const result = {};
    for(let person of people){
    result[person.id] = person;
    }

  • @karnellschultz6446
    @karnellschultz6446 Pƙed 2 lety +1

    pretty good stuff. working on some performance issues right now and noticing these patters all over the place. Not sure if this is my silver bullet, buttt very good to keep in mind.

  • @FuzailShaikh
    @FuzailShaikh Pƙed 2 lety +1

    Thanks man, I’ll be more cognisant using spread operator now

  • @helloworld_5
    @helloworld_5 Pƙed 11 měsĂ­ci +1

    this was a great video, thanks

  • @ToJak91
    @ToJak91 Pƙed rokem +1

    Not only more performant. But it's easier to read aswell.

  • @_erfanm96
    @_erfanm96 Pƙed 2 lety +3

    Right, but I didn't see anything about destructuring (the title) in the video.
    It was about the performance effect of using the spread operator for returning a new object on every iteration.

    • @jherr
      @jherr  Pƙed 2 lety +1

      That is true.

  • @ivanjasenov1220
    @ivanjasenov1220 Pƙed 2 lety +1

    Great point!

  • @KaizenCodes
    @KaizenCodes Pƙed 2 lety +1

    Great video Jack! Thank you!

  • @ShingoSAP
    @ShingoSAP Pƙed 2 lety +2

    Awesome !! 👏👏👏 Thanks for Sharing ! 👍

  • @aleksd286
    @aleksd286 Pƙed 2 lety +1

    You made me cry because I tend to write in a functioning style

  • @pushpendra-sharma
    @pushpendra-sharma Pƙed 7 měsĂ­ci +1

    Really helpful.

  • @shubhamlatiyan7972
    @shubhamlatiyan7972 Pƙed 2 lety +1

    Great information Jack, Thanks

  • @saichand5752
    @saichand5752 Pƙed 2 lety +1

    Very intresting... thanks for info

  • @personalquests
    @personalquests Pƙed rokem

    For the second example i would have used the map function it eliminates the need to create a new array on every loop. The first example okay. thank you great tutorials. i do love them.

  • @trenthm
    @trenthm Pƙed 2 lety

    Great video! Thanks!

  • @ferrben8047
    @ferrben8047 Pƙed 2 lety +1

    Love your content Jack!

  • @shinmessiah
    @shinmessiah Pƙed 2 lety +1

    Good stuff sir, love this content

  • @bigmistake5565
    @bigmistake5565 Pƙed 2 lety +2

    3:40 are they semantically the same tho? Option A ur making a new object, option B ur mutating lookup. It's just that there is no danger in mutating, as lookup only exists within the scope of the reduce-function.

    • @jherr
      @jherr  Pƙed 2 lety +2

      There is no semantic difference. You still get a new object or array either way. It’s just a question of how many objects are created and destroyed in the process of generating the result.

    • @samuelgunter
      @samuelgunter Pƙed 2 lety +1

      @big mistake with option 2, you're mutating the object that is passed in as the second argument {}

  • @SmotritelTube
    @SmotritelTube Pƙed rokem

    I would like to see the best useThrottle function in react!

  • @maksym7279
    @maksym7279 Pƙed 2 lety +1

    Thanks!

  • @Ivanandcode
    @Ivanandcode Pƙed 2 lety +1

    Nice explanation, thank you!

  • @views-qw9tf
    @views-qw9tf Pƙed 2 lety +1

    Thank you so much

  • @evanfuture
    @evanfuture Pƙed 2 lety +2

    I wonder if there's an eslint rule for this. Because object spread is certainly preferred in my codebases to avoid mutations (and to help with change detection). It would be nice to highlight cases inside reduce methods only...

  • @ChrisAthanas
    @ChrisAthanas Pƙed 2 lety +1

    Very useful

  • @samucancld
    @samucancld Pƙed rokem +1

    Concerning, I always use spread

  • @feyokorenhof
    @feyokorenhof Pƙed rokem

    Interesting. That is actually very helpful, thanks!

  • @CrazyCodingChannel
    @CrazyCodingChannel Pƙed 2 lety +2

    Very intersting, thanks a lot

  • @shinkobayashi5915
    @shinkobayashi5915 Pƙed 2 lety +1

    Thank you! Thank you! very useful

  • @sajedsoliman4780
    @sajedsoliman4780 Pƙed rokem

    Really useful one
    Thx ❀

  • @danhthanh418
    @danhthanh418 Pƙed 2 lety +1

    Great content. Thank Jack

  • @heguer87
    @heguer87 Pƙed 2 lety +1

    Good to know!

  • @user-ti1kc7qk3n
    @user-ti1kc7qk3n Pƙed rokem +1

    ê°ì‚Źí•©ë‹ˆë‹€. 제 윔드에도 읎런 ëŹžì œê°€ 많을 ê±° 같아요.

  • @12px
    @12px Pƙed 2 lety +1

    Thanks sir!

  • @Cowglow
    @Cowglow Pƙed 2 lety +1

    Lovely Video

  • @Skar38rus
    @Skar38rus Pƙed 2 lety +1

    nice tip, thank you Jack

  • @Stnaire
    @Stnaire Pƙed 8 měsĂ­ci

    You're almost there. Now get rid of the reduce and do a simple loop. Using reduce is totally useless (at least in that case) and you got a function call for each item of the loop, which is slow.

  • @reprisal0
    @reprisal0 Pƙed 2 lety +2

    Is there a list of the extensions you use for VS Code?

    • @jherr
      @jherr  Pƙed 2 lety +3

      This one is Quokka. But yeah, I'll be doing a video on that.

  • @SeaRich
    @SeaRich Pƙed 2 lety +1

    React use that to update states a lot.

  • @MrPlaiedes
    @MrPlaiedes Pƙed 2 lety +2

    No one should be surprised when polyfills cause a performance hit. That's part of the trade off, I think, for wanting a new feature without fully supporting it. Thx for the video!

    • @jherr
      @jherr  Pƙed 2 lety

      Even without polyfills this is a performance hit, because for an array of N items, with a desired output of 1 object or array, you are creating N+1 interstitial objects or arrays, all with increasing size, and then discarding N of them.

    • @MrPlaiedes
      @MrPlaiedes Pƙed 2 lety +2

      @@jherr Sure. I suppose there are a lot of assumptions here, though. Older versions of JavaScript may be due to older browser (older computer? Maybe a corporate limitation?). I am also assuming if you can use spread operators, your system should be able handle what spread is doing under the hood. Hope you don't mind my comments. Thanks for your videos, Jack!

    • @jherr
      @jherr  Pƙed 2 lety +1

      @@MrPlaiedes Don't mind the comments at all. Keep 'em coming. That being said, I ran the numbers for the performance on Node 16, which is handling the spread operator and those are the results I got. The issue really is the N+1 problem. You want 1 object (or array) and instead you are creating N+1 temporary objects (or arrays) and then throwing away N of those and keeping just the one. And each of those temporary objects (or arrays) is a complete copy of the previous one. So they get bigger and bigger and slower and slower as you go.

  • @jameshans7459
    @jameshans7459 Pƙed 2 lety +2

    What is the name of the extension used for previewing the results?

  • @technikhil314
    @technikhil314 Pƙed 2 lety +4

    I am wondering why did you not use performance.now()
    And if my understanding is correct the reduce was made to make sure you can mutate the accumulator

    • @jherr
      @jherr  Pƙed 2 lety

      Sloth and yes. :)

  • @laztheripper
    @laztheripper Pƙed 2 lety +1

    Isn't a for loop clearer and more performant? I mean besides the slick one-liners, what purpose do they serve that for loops don't?

    • @jherr
      @jherr  Pƙed 2 lety +1

      If you use ++i a for loop is very slightly faster, but you still have a raft of possible bugs that you don't with for(of) and for(in). The traditional for loop is good when you need precise control of the looping constraints, if your intention is just to loop through every item us for(of) or for(in). Those make your intention clear,.

  • @Aspiiire
    @Aspiiire Pƙed 2 lety +1

    great video thank you :D

  • @joonaskrohn6785
    @joonaskrohn6785 Pƙed 2 měsĂ­ci +1

    I could have sworn that you once had a video comparing the performance of array copying with spread, for loop and other methods. Has it been deleted for some reason?

    • @jherr
      @jherr  Pƙed 2 měsĂ­ci

      I haven't deleted many videos, and I certainly don't remember deleting a basic JS video like that. I've covered it a bunch of times though.

  • @vincentweber1359
    @vincentweber1359 Pƙed rokem

    That's also pretty nasty in terms of garbage collection. I know, the v8 scavenger doesn't have that much problems with objects that die pretty much immediately, but it's still something that might trigger a minor gc cycle early on, and I'd recommend avoiding that, especially during animations or game loops.

  • @darkmift
    @darkmift Pƙed 2 lety +1

    Coming across this I wonder.
    The spread reducer returns a new array but the other
    Returns the array passes by refrence into the accumulator.
    This may result in issues in some cases

    • @jherr
      @jherr  Pƙed 2 lety +1

      Maybe, but I think if you understand references enough to use a form of reduce where you mutate the referenced object or array as opposed to continuously creating new objects or arrays, then you'd probably know to control the provenance of the original object or array.

  • @techsy7404
    @techsy7404 Pƙed 2 lety

    I really love your content, I wanna learn the architecture thing of an application. Any recommendations or tutorials?

  • @aksyonov100
    @aksyonov100 Pƙed 2 lety +2

    I believe Ikea had that issue where you can't checkout 1000 items from the basket, site would be simply unresponsive. They have been losing money because of that simple mistake ;-)

    • @jherr
      @jherr  Pƙed 2 lety +1

      Hahah, ok. BTW, thank you for the video idea. I forgot to mention you in there. But yeah, you are right, this is mostly something you are going to run into on the node side crunching bigger datasets.

    • @aksyonov100
      @aksyonov100 Pƙed 2 lety

      @@jherr thanks to you for the channel! Learned a lot from your videos :-)

  • @artemtarasenko9744
    @artemtarasenko9744 Pƙed 2 lety +1

    So, essentially, do not return an object or an array from a loop, if you don't really want to create an additional instance of it every single iteration. That should be in the docs)

    • @jherr
      @jherr  Pƙed 2 lety

      Yeah. Don't make JS building an object that you are probably just going to throw away. :)

  • @pierre-jeanmartin5621
    @pierre-jeanmartin5621 Pƙed 2 lety +1

    Just look at the transformation priority premise: reassigning a new object is the worse transformation

  • @LukasPetry
    @LukasPetry Pƙed 2 lety +1

    Yes, of course. In this case totally on point, however be patient, in other scenarios mutating objects or arrays gets you into trouble. So I think it makes a lot of sense to default on spreading as this is more of a performance optimisation

  • @mirtanvirahmed3868
    @mirtanvirahmed3868 Pƙed 2 lety +1

    which extention do you use to see real time results in the editor? Like when you put you cursor on a object, editor shows a result in the right side of that line??

    • @jherr
      @jherr  Pƙed 2 lety

      Quokka: quokkajs.com/

  • @Petertumulty
    @Petertumulty Pƙed 2 lety +3

    Does this anti-pattern also apply to map? Would either of these be considered anti-patterns?
    const offices = officeLocations.map(({ id, title, address, phone, fax, slug }) => ({
    id, title, address, phone, fax, slug
    }))
    or
    const offices = officeLocations.map((office) => ({
    ...office
    }))

    • @jherr
      @jherr  Pƙed 2 lety +4

      Map doesn't have the same unexpected behavior, because you are creating objects 1-to-1 to match the array. Where in these reduce examples you are creating a single object or array, and with each iteration it's getting bigger and bigger so the copies are more and more expensive as the array size grows.

    • @Petertumulty
      @Petertumulty Pƙed 2 lety +1

      @@jherr oooohhh i see, mind blown! Thank you

    • @sigmawolf228
      @sigmawolf228 Pƙed 2 lety

      There's no such a thing as anti-pattern with Jack. He's a Senior HelloWorld Developer, what are you talking about?

  • @AlexJohnSuarez
    @AlexJohnSuarez Pƙed 2 lety +1

    What are you using that will output the result in file, that you dont need to do console log?

    • @jherr
      @jherr  Pƙed 2 lety

      Quokka quokkajs.com/

  • @savolus
    @savolus Pƙed rokem +1

    using `new Map` with `hash.set(key, value)` may even be faster then using object like this

  • @TheZayzoo
    @TheZayzoo Pƙed rokem

    Does anyone know that add on for the preview in the blue text?

  • @arcosd63
    @arcosd63 Pƙed 2 lety +2

    Hey, Jack, good show. May I ask how do you get the comparison performance chart on your screen?

    • @jherr
      @jherr  Pƙed 2 lety

      That's After Effects. I use a couple of effects on it to swivel it, then do the animations.

    • @arcosd63
      @arcosd63 Pƙed 2 lety +2

      Hey Jack, thank you for your prompt response. I am really enjoying the way you explain material, so I'm going to look into one of your courses.

  • @saichand5752
    @saichand5752 Pƙed 2 lety +1

    What's the extension you are using??

  • @victorlongon
    @victorlongon Pƙed 2 lety +1

    That makes sense but this is really only relevant if you have really big data. I mean for most people in most scenarios it will only be like some dozens of objects so maybe it is a good idea to keep the more readable code? But again it totally makes sense depending on the volume of data you are handling

    • @jherr
      @jherr  Pƙed 2 lety +4

      Completely agree, I mentioned that at one point that the impact of this on the client would probably be nil because of the smaller data sizes. But if you're making a library, or you don't know the context or the potential maximum size of the data set, then this is something you should be aware of.

    • @supergoteam
      @supergoteam Pƙed 2 lety +1

      A single big data set is of course one way of getting there. But also think in terms of nested small datasets. Loops in loops can quickly that up that big O and bring optimisations like this back into focus.

    • @xinaesthetic
      @xinaesthetic Pƙed 2 lety +2

      If you’re in a situation where you care about GC pauses (games etc), that is another reason to be very mindful of unnecessary object allocations. Also, while there’s definitely some truth in it not always being necessary to think about scalability when you know your code only runs on small datasets, I think we have a lot more bloated and slow software than we need in the world and it’s ultimately contributing to data centres etc consuming a lot more energy and having a much higher carbon footprint than they should.

    • @victorlongon
      @victorlongon Pƙed 2 lety +1

      @@xinaesthetic for sure. I thought about writing stuff for games for instance and also in those cases maybe you don't even want immutability at all (in a lot of scenarios at least) ?

    • @supergoteam
      @supergoteam Pƙed 2 lety +1

      @@xinaesthetic Absolutely agree especially on the points of large scale wastages. We generally code with human first attitude but keeping an eye on easy optimisations where we can. Just because we can be lazy doesn't mean we should. On the flip side of that optimisations first is something we haven't 'had' to do for quite some time now and can really slow a project down. Like all things in life it is about finding a balance.

  • @OlDirtyLZA
    @OlDirtyLZA Pƙed 2 lety +1

    Question does this only apply to reduce method? I wonder would using the spread operator in a reducer cause any performance issues?

    • @jherr
      @jherr  Pƙed 2 lety +1

      I can't think of any of commonly taught pattern that has this kind of performance issue. But I'll definitely have more of a think about it.

  • @hoads19
    @hoads19 Pƙed 2 lety +2

    The benefits of the spread operator is immutable. Is the second method immutable?

    • @ukaszzbrozek6470
      @ukaszzbrozek6470 Pƙed 2 lety +1

      You create one object and you mutate that. Original data isn't change. There is no down side to that mutation.

    • @jherr
      @jherr  Pƙed 2 lety

      It is not immutable, but, let's think about what's happening here. You have a set of N elements from which you want to derive one object or array. And you can either create N+1 objects (or arrays) and throw away all of the N in the process, or you can create one. And in both cases you get a new object or array. Does the gain of having N temporary objects that you throw away that are immutable outweigh the benefit of using a mutable process to derive the one output? And with either process the resultant object (or array) is itself mutable (unless you freeze it).

    • @shunia
      @shunia Pƙed 2 lety +1

      The video is great and at the point, but it's still insane that only one comment mentioned this.
      If you have a really huge dataset and are trying to reduce it, it's mostly wrong at first place. You either take part of the data out of the dataset then edit, or you just use a more efficient way to store your data so it's performant to edit.
      And if you are doing something mutable to the original dataset, it could cause unwanted behavior in components which used the same dataset, because although the dataset contains the data didn't change, but the data itself has been changed.

  • @mysuperemecy
    @mysuperemecy Pƙed 2 lety

    It was realy great learning, would you suggest any book which covers such anti patterns in good detail

  • @dwakeling1
    @dwakeling1 Pƙed rokem

    I think you may have gotten the big O notations the wrong way around.
    From my tests its the object that is ^2 and the array is ^3

  • @sfansari007
    @sfansari007 Pƙed 2 lety +1

    This is amazing. I never thought that internally it may impact so much. What's the name of that extension which is showing the output on hover

    • @jherr
      @jherr  Pƙed 2 lety

      Can you cite a time reference? I think it's just the usual hover.

    • @roberthaforsson9687
      @roberthaforsson9687 Pƙed 8 měsĂ­ci

      @@jherr It is on min 3:15. For me its not the usual hover

    • @jherr
      @jherr  Pƙed 8 měsĂ­ci

      @@roberthaforsson9687 That's Quokka. It's an extension.

  • @chakhmanmohamed9436
    @chakhmanmohamed9436 Pƙed 2 lety

    Mr. Jack i looooove your videos. I would love a course recommendation if you know any.

  • @CarnivorousSpork
    @CarnivorousSpork Pƙed 2 lety +1

    Wondering if you could elaborate on the underlying aspects that make this slow in JS but performant in others like Scala?

    • @jherr
      @jherr  Pƙed 2 lety +6

      In JavaScript, if you use this anti-pattern on N items you'll get N copies of the output object (or array) plus the one output object (or array) that you actually want. And each copy will be successively larger than the last.
      Scala has referential data structures so an array can say; "I'm just this array over here, but with this added value." So instead of having N arrays you are basically creating a linked list of related arrays. Still probably not as fast as simply mutating an object (or array), but that's probably mitigated by it being on the JVM and being compiled.

    • @xinaesthetic
      @xinaesthetic Pƙed 2 lety +1

      I made a similar comment a couple of minutes ago, so apologies if I’m repeating myself.
      It’d be interesting to compare to something ClojureScript or Elm that should be using similar data-structures in a JS context.

  • @michallevy9806
    @michallevy9806 Pƙed 2 lety

    So creating new object/array in every loop is slower than modifying the existing object/array? What a revelation :)

  • @Smileyassassin47c
    @Smileyassassin47c Pƙed rokem

    But they are used for different purposes. I don't feel like this is an apples to apples comparison(i mean it is technically but not when you think about the problem you're solving), you use spread when you specifically want to create new objects instead of using the references, such as when tracking state changes.

  • @chippycode
    @chippycode Pƙed 7 měsĂ­ci

    Please, which plugin suggest the output at the end of the line?

    • @jherr
      @jherr  Pƙed 7 měsĂ­ci

      Quokka or Console Ninja.

  • @fredbluntstoned
    @fredbluntstoned Pƙed 2 lety +1

    So the fix is to not use the spread operator to create a return object in a loop if you can simply reuse an already created object?

    • @jherr
      @jherr  Pƙed 2 lety

      Yes. Simple. But, unknown to some folks, so... a video. :)

    • @s3xta13
      @s3xta13 Pƙed 2 lety

      @@jherr I believe that most are taken by the immutable lintings. At least in the FE world

    • @jherr
      @jherr  Pƙed 2 lety

      @@s3xta13 Confused, are you saying that eslint would fix that for us?

    • @s3xta13
      @s3xta13 Pƙed 2 lety +2

      @@jherr no no... But mainly most configurations for eslint shows a warning saying that a .push in an array is mutating value and probably isn't what you want. What I'm saying is that most of newcomers to js or react (for example) can be led into fixing a .push to the spreading option...

    • @jherr
      @jherr  Pƙed 2 lety +1

      @@s3xta13 Ahhhh, gotcha, that would be unfortunate, because in this case you really want to use the much-maligned push.

  • @petrtcoi9398
    @petrtcoi9398 Pƙed rokem

    Great video. But why TS just don’t convert spread operator to “fast” version of code?

    • @jherr
      @jherr  Pƙed rokem +1

      TS's core concept is that you should be able to strip the TypeScript annotations from the code and be able to run the JavaScript as-is. It doesn't make modifications to how your code works. It just checks types.

    • @petrtcoi9398
      @petrtcoi9398 Pƙed rokem

      @@jherr Sorry. Not correct answer. I mean Babel

    • @jherr
      @jherr  Pƙed rokem +1

      @@petrtcoi9398 Ah, ok. It would have to understand the semantics of what you are doing. If you are doing a map then a spread is appropriate if you want to create a new object to replace every element in the array. I wouldn't trust any transpiler to make that call.

    • @petrtcoi9398
      @petrtcoi9398 Pƙed rokem

      @@jherr OK. I see. Thank you

  • @thepetesmith
    @thepetesmith Pƙed rokem +1

    Using “quokka”? What’s that?

    • @jherr
      @jherr  Pƙed rokem

      It's a VS Code extension that provides interactive workbooks running JavaScript or TypeScript.