The first reason is actually why I like arrow function over classic function definition. Code flow for me goes from definition to implementation from top to bottom, instead of what you mention about "important" code at the top. If I need something I like to know this "something" exists before trying to use it, and using arrow function along const enforces just that.
Same thought here. I would never have the important stuff on the top. Especially because of how hoisting works. If you can't always do it, you should never do it
@@Shulkerkiste it absolutely makes sense just for brevity to put functions in constants,especially so with arrow functions. Of course not when you write them out with all the superfluous brackets he was using and a useless 'return' statement. And however clean your code is, the constants you need must be declared before you use them, whether they contain functions or other values
True, you need to create function thene use it, this is how code should work. If hoisting were good thing let and const would have hoisting to. You should always create function thene use it no metter if you are using function expression or decloration.
@@indriq78 That is really highly subjective. I personally dislike if a function on line 10 is calling a function that's on line 100, I don't really care if the most important logic is first in the file or not, I just care that things are defined in order so that they are defined before they are used. It's just easier for me to piece together things if they aren't just randomly spread throughout a file. I can also read two things at the same time on same IDE/editor page if I have two functions one after another, but the second one is calling the first one. I can just have both of them in the same view without using multiple editor views or whatever. I feel the same way about variables as well, but with variables it makes more sense to have them defined before using because variable hoisting is just weird in normal code flow when reading code.
My opinion. 1. Hoisting -- I personally prefer to write code in this order anyway, the outer layers (i.e. the main logic) is further down, so I always jump straight to the bottom of a file if I want to know what's getting executed. I guess this just might be preference. I also come from a background of pure mathematics where everything is structured in a way where there is no hoisting, everything is ordered naturally, that is, sequentially. Regarding your example with helper functions, these can always be moved to a different file, that makes more sense if you believe there should be a separation.
Although the IDE helps with this to some degree, it is generally more difficult to find the function from an invocation if they are split between multiple files. Still, I appreciate the different viewpoint. Looking for the top-level calls near the end is probably more natural for coders who are used to more imperative programming styles.
as an engineer who has coded in many languages over 20 years, JS is the one that is the most painful to deal with BECAUSE of 'hoisting' and the changing context of 'this' depending on how it's called. Among other things, JS has so many odd quirks that make it a pain compared to many other languages.
I feel your pain. The descriptions of the this keyword across tutorials on RUclips are confusing. I would start by looking at tutorials on the execution context. Once you get that then topics such as hoisting, scope and the this keyword become clearer. ruclips.net/video/Nt-qa_LlUH0/видео.htmlsi=bvcDZ-ET88oZeT_R
"Dynamic this" solves an Expression problem though. It would be a disaster to simply remove it. An alternative object extension mechanics would have to be provided before that.
Slight correction in your event handler, "this" is the same as event.currentTarget, not event.target. The target is the element that was clicked on while currentTarget is the element with the event handler.
yeah, just to make it a little clearer: (i) event.target is the node where the handler function was written (ii) event.currentTarget is the node(parent) where said handler function bubbled up to - where event currently is being handled.
@@redsnflr Not sure what you mean by where it was written. The handler is called (I think you may have meant this?) when the element, or descendant of the element, that the event listener is registered to is clicked (if it's a click listener, as is the case here). If there are no descendant nodes, or if you just click somewhere in the parent where the child is not, e.target will then equal e.currentTarget, ). If anyone wants to better visualize it, just search event propagation for some easy to understand diagrams.
@@phillipandrew87 yes, where it's "handled" is where you write the event handler function, e.target is static but currentTarget is dynamic based on where the event currently is.
i think that calling things AFTER defining them makes much more sense, I get super confused when the file doesn't have to respect a specific order... and seeing that so many people do terrible crap when they are not forced by linters or interfaces like typescript, I think it's very much needed to adapt to these better practices
On a real production project I almost certainly will have each of my functions in a separate file (excluding anonymous functions and callbacks) and when passing callbacks I usually want to bind the parent context like it is default with arrow functions, so I'm the opposite: I use the function keyword only when an arrow function does not cut it. Which is rare.
Yeah, the example util functions given are great examples of functions you'd never even have in the same file as where they're being used in the first place. Sure, having the functions below the main logic of the file makes sense, but having those functions in a different file entirely makes even more sense. At which point using function keyword vs arrow functions don't really matter in terms of readability anymore.
One of those rare cases is when you want to use the arguments keyword!! Like, you made a callback, but there are no docs, so you print out all the arguments of the callback, this doesn't work with arrow functions sadly
Reason 1 is also why I use arrow functions. Not out of puritanical belief or anything, but the backend language I work with the most is F#, which requires everything to be declared before it can be used. And when writing functional Javascript (or especially Typescript), the languages are actually extremely similar and I think it's the best functional approach. F# enforces order of files too, which can't really be done in Javascript, but I wish it could be.
I think arrow functions do not require context switching, I may be wrong. Thus for small snippets of code I prefer using arrow functions and for larger snippets I use normal functions. As for organizing code, whether I write code at top of my file or bottom doesn't matter to me that much due to modularity, I do not write any thing else in the main script rather one main function and then calling it. But that's just my style. Honestly I do feel all the rules and guidelines for writing clean code is meaningless if your code is not performent. Most of the time this leads to unnecessary abstruction that often have many unnecessary instructions that are not needed but still called only to keep the structure "clean". For example, looping over same array multiple times in different functions where everything could be done in a single loop causing much less memory access (one of the biggest bottlenecks). Javascript is not a compiled language, but and interpreter. So from compiler diesign perspective, the optimization done by jit compilation is no where near like languages like c, where compilation in release mode throws away all the fancy abstruction and completely reorganize only performent code. Sadly dueto the dynamic nature of js and being and interpreted language this is not possible. So developers should be mindful of the cercumstences. However again it depends on how performent one wants his code to be. For a dataview kind of website it doesn't matter, but for things that requires high amount of computation it matters. As an example, working with canvas 2d if you floor the arguments before passing them to the function, you will see a significant boost in performance. The reason is simple, interpreters are not as smart as compilers when it comes to optimization. The point I want to make is that function calls have costs .
Ok, so now I have two things I disagree with you: not using semicolons, and now the arrow functions :P To me, having to define the functions before they're used is not an issue, but a plus. It helps when you work on a team where usually a few devs are messy with their code, so these small things that force you to be a bit more organized are really helpful. Same goes for some people's neverending creativity for using 'this'. With arrow functions we avoid several errors that cause bugs. So in the last few projects I've worked on, we use the opposite strategy: everything's an arrow function except for some specific cases. As for the syntax, it's just preference/getting used to. Anyways cool video, it's nice to see different approaches / trains of thought.
WDS has some hot takes and I think he's doing it for the controversial comments and views. Almost every short I've seen from him is just objectively bad, but it drives a lot of views and comments. Most of his project tutorial videos have much better information, but the individual "why I don't use X" videos blow. His "why I don't use the useEffect hook" video is a golden example of a really awful take for no reason other than rage bait
I think for react is more cool and clean code to work with arrow functions with const/let, because you won't doing any hoisting since your state and stuff is being defined at the top of your component function, and any helper/handler function as well don't need to be hoisted
@@Issvor Assume mistake over malice. I don't think he intentionally does it for rage bait; I think he's just mostly a self taught and solo developer who doesn't have all the information.
I haven't seen this useEffect short but I personally put a lot of effort into avoiding using useEffect due to it's re-render strategy and awkward handling. However, I don't avoid it at all costs. Sometimes it's the perfect (or only) tool.
It seems to me that almost everybody uses arrow functions for the same reason: to give a structure to their code. It's like telling a story without giving spoilers.
as solo dev its okay but when you work with code that someone else wrote, hoisting is pain in the ass because in comparison, if there are no strict rules where we should place functions, hoisted functions is immediate "peek definition", because they can be lower in file or higher, whilst arrow functions enforce you to define them before using, that makes them not significantly easier but quite a bit, also no "this" after dealing with class components in react i truly started hating hoisting
I agree with Kyle here and use normal functions for helper functions and arrow functions for callback functions. It's much easier to identify a function this way, plus hoisting is a bonus.
Love your channel, man. I love that your videos are concise and straight to the point. Learn a few new things everytime I watch your content, even if it's a topic I already know well and you give me a different perspective on it.
Yeah. It's like saying "I don't use Typescript because it's more work". Correct (in a sense), but that work is there to actually make the code less likely to throw errors along the way, when the project grows much bigger. Hoisting is ok for small script and such, but I would avoid it as much as possible if growth is expected. Also maybe I'm weird, but I like the arrow look, especially with no parameters it looks like it's taken from an ancient occult book lol
@@firedforfighting I wrote what i understood from the video, but I side with arrow functions coz I want errors to be thrown at development stage and not at the prod stage if they went unnoticed while using regular functions.
The main reason I would use const arrow is the fact that they can't be modified. If you do (with a function) formatNumbers = [1, 3] somewhere bellow It would "destroy the pointer to the function itself".
Basically you should prefer not to mutate almost anything unless it's better for a specific case for some reason (readability, performance, can't do otherwise, etc). So mutating a function should pretty much never happen - whether you define them with function or const
@@IceMetalPunk If you need to enforce the idea that you shouldn't be mutating a function reference, then you almost assuredly have far more serious problems within your team...
I thought I was alone with this concept. I hate using const over function. Most of the reasons you said but primarily because when I'm scanning code for a variable or function I don't want everything to look like a variable. And hoisting, I don't want to worry about where I'm defining my function. The funny part is it's not even really any shorter of syntaxes. Const name () => is is literally one less character than function name() . You can omit the brackets in arrows but I often use them anyway.
You make a lot of good points there, especially the ReferenceError which I honestly hadn't come across yet, because I work with nested functions almost exclusively. Maybe it also has something to do with the fact that to me as an old C coder defining a function before use is as natural as breathing. The reason why I love arrow functions so much is because unlike all the syntactic sugar around functions, classes and methods todays programmers grow up with, assigning an arrow function is very close to the bare bones of functions, which, when all's said and done, are very little but an address to jump to in memory. I must say, I disliked JavaScript for the longest time for its lackadaisical typing and conventions, but ever since I began looking at it from the bare-bones perspective, it has fast become my favourite language, even before Lisp and my beloved C
Yes even I didn’t face in react but maybe its issue in vanilla javascript I use it still I have a habit of writing function in order then call them at the end just like other programming languages 🥲.
@@redsnflr Funny you should ask. It took me a while to discover TypeScript, but I instantly fell in love all over again 😉 Honestly, it's not "proper" hard typing, but that's what makes it so interesting - it holds a mirror up to your coding habits showing you what hard typing made you take for granted.
Good points, but this convention breaks as soon as you need to type a function in TypeScript (think of FC). Plus, I've found that relying on hoisting generally results in poorly organized codebases unless you're working on a tiny project w/ a single file (where arguably convention wouldn't matter that much anyway). If you think "what if I want to run some code in a utils.js file where I export my helper functions?", then I would say look back at your architecture and think whether you really want to run arbitrary code in a utilities file that's meant for "utilities". Idk, these are some of my reasonings to use arrows everywhere (except in OOP & decorators). Everyone should use the approach they feel most productive in as long as they know the differences between them 💙
For reason 1. If I have many helper functions and especially if I want to use them in many different scopes or in different files. I like to have them in an object, possibilty in a separate file that can be imported. This way, I have a structure where I don't have to scroll past the function expressions all the time as I can keep them in a separate file or collapse them all together, and this works really well with arrow functions. But it really depends on the complexity of the project naturally. E.g.: ``` export const helperFunctions = { helper0: () => { console.log("I help") }, helper1: () => { console.log("I help too") }, helper2: () => { console.log("I help three!") } } ```
Your use of hoisting is what the Clean Code book teaches. It kinda reads like a newspaper article where the important stuff is on top, the more you go down the more details you get. For example if I'm going to explain how to make a pepperoni pizza, I can say: "Roll the dough out, spread tomato sauce, grated cheese and sliced pepperoni on top in that order. Then put the pizza in a preheated oven on 200 celcius for 30 minutes. Slice the pizza and eat when sufficiently cooled down." This is already pretty verbose but technically for most people this is enough to know what we're making and how. The "helper functions" would then in order that they appear underneath the main function. So in this case: "The dough is made by..." "The tomato sauce is made by..." "You grate the cheese by..." "The cheese is made through..." "Slice the pepperoni in thin 2mm..." "The pepperoni is made by..." "The pizza is sliced in 8 different equal parts" I could put the oven preheating details also in it's separate section but making it too generalized actually takes away descriptive power. So it's important to keep track of your level of abstraction, don't mix the different levels too much and don't go too deep that you get lost. When you open the file you immediately see what the code is doing. You scroll down to see how it is being done exactly.
You make a good case, but you stretch the analogy too thin. Ideally, you wouldn’t have your functions lain like that in a single file to where they can result in this issue to begin with. That, in my opinion, is bad code. Trying to remedy that with hoisting is not clean code, it’s bandaging some (likely) not-well-thought-out code organization. More so, your analogy can be used to derive some benefits for the arrow syntax. With hoisting, if you end up with the scenario in the video, functions that compose or use each other need not be declared in a meaningful or logical order. Arrow functions force you to order your functions from the most self-contained to the most complex. This way, you are guaranteed to find that the steps for making a basic pizza dough are placed strictly before the steps for a mozzarella-stuffed dough, and not jumbled anywhere else. THIS reads more like a recipe book.
I use function expressions at work because that's what's used there and it's not important enough to rock the boat. But I really dislike them in most cases. I find regular function declaration syntax much easier to read. I use arrow functions a lot, but as in the video, mostly when defined inline as a callback, or if I need to close over `this` (very rare). Hoisting is sometimes annoying but mostly not an issue since most of my functions will be in module files rather than defined where used.
A lot of people commenting about putting helpers in another file... A couple things: 1) Definitely do that. I think Kyle already knows that's best practice. But for the sake of brevity, he makes his point here not mentioning it. 2) If you DIDN'T do that, and kept all helpers in the same file, I think what Kyle says makes perfect sense -- important logic at top, function definitions below. 3) Either way, for DECLARING functions, I agree that the traditional function syntax is clearer -- yes even when declaring them in separate files/modules. 4) Arrow functions are awesome, but 99% of the time I use them I would agree with Kyle here -- it's in the context of anonymous lambdas.
I had the "this" problem two days ago and could not understand why the arrow function didn't work, and the function did. Thanks for explaining it! I ended up just telling the linter to ignore my function, lol.
I know about hoisting but I don't rely on it. I write regular functions as much as possible on the "top-level" to take advantage of the `function` keyword as you mentioned, and at the top of the script so that it "flows" naturally
If you use typscript like almost everyone else, then that means your code will be transpiled into es5 anyways, hence your functions will be actual functions regardless of the declaration method and be hoisted anyways. i got your point tho
To me, hoisting is one of the most terrible features of JS, and it should be removed and burned. The idea that your code can reference things that you haven't even defined yet is just asking for spaghetti code. Removing the possibility of hoisting is one of the biggest reasons *in favor* of arrow functions, in my opinion. Module imports can clean it up if you don't like scrolling through the definitions to get to the main logic.
I always default to arrows unless I need to create a new context. I'm not bothered by functions clogging up the top of file because they probably belong somewhere else if you have that many of them.
My preference is to use arrow functions only where there's an immediate return, or if I need the outer this. `function a(b) { return b+1 }` is less typing than `const a = (b) => { return b+1 }`, but more typing than `const a = (b) => ( b+1 )`. In general, this allows the reader to quickly make assumptions about the code - if you see `=> {`, you know to look for a `this` referencing the outer block
I am a Vue dev and in Vue 3 I exclusively use arrow functions. I a helper function is required at the top it's placed in a file of it's own. I prefer to group blocks based on what they do rather than just put "important" functions at the top.
I prefer function keyword because it is clear that it is a function, not a const variable. Readability. It gets confusing when everything starts with const.
The people in the comments trying to refute the first point of the video are forgetting one thing: In a team, one programmer should avoid making the dreams of other programmers impossible. In some cases (especially very small libraries) it totally makes sense to put the public API at the top and less important functions at the bottom.
Definitely the most important reason for understanding whether to use ES5 or ES6 function syntax is with 'this' binding, especially when it relates to creating methods. That is actually important for the functionality. While I appreciate and understand your 'main reason' for better layout flexibility with hoisting, it is simply personal preference and isn't as important imo. Either way, thanks for the reminders. 'This' is and will always be confusing forever.
Haha, good thing we're mostly past using `this` in JS these days since there's a much bigger focus on functional programming. I don't think I've used `this` for years since when I did jQuery stuff. And I'm happier for it.
As others have said, the flow of code as is executed is generally first defining things and then using them, so having functions before executing them makes sense. Now it’s fine to have a different preference but you can’t escape the reality of how code is executed entirely. If you import a function from another file, for example, it has to be at the top of the file. At best you can partially change the order by utilizing hoisting but not entirely, so you still end up having to jump around a file in certain cases. As someone who values consistency I find it much easier to simply go with the flow of code execution and generally expect entry points to be at the bottom of a file. Then there is the whole thing when working with a team and/or an existing code base, you generally will want to match the style of the project, so always keep that in mind. :)
Not to mention that defining your helper functions as arrow functions can usually make them much more compact (if they can be written as one expression) and make scrolling through them much less of a big deal.
Personally I like definining react components as `function`. E.G. `function App() { return }` rather than `const App = () => { return }` (assuming you have some logic in it). However, the benfit of arrow functions in React can be for TypeScript typings, like `const App: React.FC = (props) => { return }`, but I find these explicit types unnecessary since the implicit ones are IMO just as good. But I've used both styles, and at the end of the day, the most important thing is consistency within a project, and harmony with other devs :D
Most of the concepts in this channel are just personal enlightenment. And that's one of the reasons I don't like RUclips. There are some good channels but most of them are crappy. And also, using hoisting was a bad idea from the beginning. It reverses the flow logic and overtime makes things messy. These channels always rely on small code pieces. You can make everything right with a small code piece. The issue is to make it valid for huge repos.
i m a full stack developer.. I know this concepts.. but refreshment of this concepts and the explanation in your videos gives my mind a kind of comfort and boosts confidence for unknown reason.. keep up the good work friend.. your video was inspiring for me to keep working as dev !!
1) Avoiding hoisting is a good thing. It's not a difficult concept to understand but one that has generally only added confusion and errors in JS. 2) If none of those functions are important, then why were they written? The example here is a case where it is both too trivial to support the argument AND a more complex example would be better done with modules, as others have noted.
I’m almost always dealing with other people’s code right now so my own preferences are pretty mercurial, entirely down to how I’m feeling on whatever small project I’m working on. I’m usually consistent within a project, but across projects it can vary. I think I usually use regular functions when just defining them in a module because when I’m naming them arrow functions don’t save much if any typing. That’s about it.
I devide my code in sections, one being helpers functions, all declared with arrow functions. Later I have one update function, which all actions go through, so I’m never in doubt whether I’m looking at a helper function or the core of it, because there is only one core update function. The rest is helpers and sometimes i move to another file and have them all imported. Nice and clean 😊
That's a good reason, I also like to have details of implementation at the end of the file below everything else. But there are ways around functions declaration (is that a right name for using function keyword?). When (if) you use react components you can just put helper functions at the bottom, as the component will be ran later than those, so they will exist at that point. Also those helper functions can just go to a separate file (which they probably should). So I usually still use const/let functions.
1. Use function is more semantic 2. There is no need to use the arrow function to define the functions always in modern JavaScript or TypeScript, especially if the bundle file is not concatenated directly. 3. Because of the scope of the variables in the function, the use of 'function' is clearer. 4. Readable and Maintainable...
IMO, helper functions should always come first, it doesn't make sense to use things which aren't yet defined. And if it's clogging up your file, extract them into a dedicated file.
Everyone is entitled to their opinion, and if this works for you cool. But if code like you've written were to cross my path professionally on any team I've lead it worked on it'd get kicked back from code review. Hoisting can be a pain to debug if something goes wrong. And while you might not have a problem a jr dev who comes in behind might not be the same.
This is why I don't like JavaScript (especially in backend). Billions of ways to do a single thing is a double edged sword. Sure it allows more than one way to do a task. However, it adds unnecessary complexity to the codebase.
Interesting take. Like a lot of the commenters, I define/declare functions at the top whether using the function keyword or arrow functions. I'll even look at my code below and go back up and cut/paste the functions in the order in which they are called. It just works with my brain that way. But I think one advantage to putting your "important code" at the top is that once the functions are written and tested, you might argue that there is no need to see them because when writing the "important code" and using tested/proven functions, you don't need to be concerned with the implementation. However, that is one of my issues. I always concern myself with the implementation. Slows me down sometimes. 🙂 Another thing I will say is that sometimes it takes a second to see whether something is a function or a const variable if they are all bunched together so it becomes more important for readability to use white space properly and have some order to defining const someFunc => oneliner; vs const someVar = value;
Another reason some might prefer regular functions over arrow functions for callbacks is that you can name an anonymous regular function. Makes it a bit easier in a stack trace to quickly see the source of the error. Personally not for me, but I did occassionally find it useful when I had to write IE-compatible code back when callbacks were king and promises (let alone async await) weren't around yet. Thank god those days are gone.
Hosting, very much like 0 type safety, is what gives us developers the freedom do things that causes bugs and/or confusion without any real benefit. The reason you mentioned why to *not use arrow functions* is the exact reason for why I think you should use them. Having a file with "a bunch of nonsense" at the top which you have to scroll by to get to the meat of it all is indeed not suitable. Therefore these helper functions shouldn't be declared in the same file as they are being used in and rather be imported at the top.
Inside my React components I use arrow functions to implement event handlers and inner functions, I rarely found myself relying on the 'this' construct. But I think it's ok.
At work we just use modules for commonly used helper functions and import them. For things like onClick functions we use arrow functions defined at the top of the react file underneath the useState declarations.
This is really a personal preference situation. My brain likes consistency. It’s so difficult for my brain to process differing syntax for the same thing. If I have functions and arrow functions in the same code, then I start to loose track of what’s going on and have to put in more brain power. Its much easier to see => and know that what I have is 99% likely to be an arrow function. For context: I used to be an avid function hoister whenever possible. Context Edit: 1. I don’t used “this” often
I mean... if you're putting all of those helper functions in the same file as the "actual" important code, maybe the function syntax isn't the problem. But I agree. The "function" keyword is better to read than a const + arrow function.
in the arrow function, 'this' always refers to the main window whereas in the normal function 'this' refers to the document or the element to which the event listener is added.
Год назад
My rule is high level functions are in the form of named functions, while anonymous functions are arrow functions. Oh and no single letter variables outside of for loop indexes. Readability and maintainability drive the choices.
I tend to opt out of code that can mutate outside state by default. Using arrow functions/ closures that automatically capture state outside of their defined scope can open doors for silly bugs.
I assume you've never worked on a massive code base where you end up in scope hell from legacy code you or 20 other developers wrote. There is a place for everything, and let and anonymous functions are a godsend.
If you have helper functions, I would maybe share the main code in smaller pieces, so you can put those functions into their own files and then use it on the main code.
Inner functions are where I'm most conflicted at. If I'm writing closures, I'll write the inner fn in the regular syntax. However if it's a fn that is used as a callback in e.g. event listeners and I'm taking it out of the function call for whatever reason (e.g. making the code read cleaner), I'll write it in the arrow syntax instead If the inner fn is a one-liner, I'm more inclined to write it in arrow too regardless of what I said above, to save on the curly braces and the explicit returns
There's a mistake in the thumbnail code -- iDislikeThis should either not have the curly braces (which would cause the result of a + b to be returned implicitly) or else it needs the keyword return before a + b.
This IS the reason I like them. :)
Put helpers functions in another file and load it
ditto
Yeah. If all the helper functions are hidden at the bottom of the logic, that seems like code that is not easily shared and is at risk of repetition.
I was thinking the exact same thing.
100%. Makes the code that runs with helper functions easier to debug when you can just put it side by side with the helper function file
Also makes much more sense coming from any other language where you need to declare your functions and classes before you can use them.
The first reason is actually why I like arrow function over classic function definition. Code flow for me goes from definition to implementation from top to bottom, instead of what you mention about "important" code at the top. If I need something I like to know this "something" exists before trying to use it, and using arrow function along const enforces just that.
I was thinking the same thing !
Same thought here. I would never have the important stuff on the top. Especially because of how hoisting works. If you can't always do it, you should never do it
@@Shulkerkiste it absolutely makes sense just for brevity to put functions in constants,especially so with arrow functions. Of course not when you write them out with all the superfluous brackets he was using and a useless 'return' statement.
And however clean your code is, the constants you need must be declared before you use them, whether they contain functions or other values
If it's about code flow, it's not like classic functions can't be moved to the top.
Similarly, we don't put import statements at the bottom of the code
The first reason is why I use arrow functions, i have to have some structure in my code not random mess with fn declarations between usage
utilizing hoisting and putting the actual solution on top is less messy than putting a ton of "intro" in front of the important part.
True, you need to create function thene use it, this is how code should work. If hoisting were good thing let and const would have hoisting to. You should always create function thene use it no metter if you are using function expression or decloration.
@@indriq78 That is really highly subjective. I personally dislike if a function on line 10 is calling a function that's on line 100, I don't really care if the most important logic is first in the file or not, I just care that things are defined in order so that they are defined before they are used. It's just easier for me to piece together things if they aren't just randomly spread throughout a file. I can also read two things at the same time on same IDE/editor page if I have two functions one after another, but the second one is calling the first one. I can just have both of them in the same view without using multiple editor views or whatever.
I feel the same way about variables as well, but with variables it makes more sense to have them defined before using because variable hoisting is just weird in normal code flow when reading code.
I just move all the functions to another fileto have a cleaner environment
@@indriq78 but the functions in this case should be in another file...
It’s refreshing not seeing a title like “STOP DOING THIS” whenever I see that, I just scroll passed the video
My opinion.
1. Hoisting -- I personally prefer to write code in this order anyway, the outer layers (i.e. the main logic) is further down, so I always jump straight to the bottom of a file if I want to know what's getting executed. I guess this just might be preference. I also come from a background of pure mathematics where everything is structured in a way where there is no hoisting, everything is ordered naturally, that is, sequentially.
Regarding your example with helper functions, these can always be moved to a different file, that makes more sense if you believe there should be a separation.
Although the IDE helps with this to some degree, it is generally more difficult to find the function from an invocation if they are split between multiple files. Still, I appreciate the different viewpoint. Looking for the top-level calls near the end is probably more natural for coders who are used to more imperative programming styles.
Coming from a C++ background, I anticipated that function declaration before its usage was the norm..
good point here. I think they have a reason to add the strictness to "const"
I agree on using the function keyword for defining small helper functions. But I still like to define them before using them.
Yea, me to :)
for the first reason you mention, I think it's better to split the code to multiple files so when you use them you just import them where you use them
C-style programming :)
@@chbrules it's just clean coding.
@@ChillAutos C for clean
@@pepperdayjackpac4521 *Memory Leak stains code two seconds later*
as an engineer who has coded in many languages over 20 years, JS is the one that is the most painful to deal with BECAUSE of 'hoisting' and the changing context of 'this' depending on how it's called. Among other things, JS has so many odd quirks that make it a pain compared to many other languages.
it is A POWER of JS, it is it's POWER !) not a weakness or a pain, it is it's POWER !)).
hey man, if i wanna became a backend developer what language would you recommend to start?
I feel your pain. The descriptions of the this keyword across tutorials on RUclips are confusing. I would start by looking at tutorials on the execution context. Once you get that then topics such as hoisting, scope and the this keyword become clearer. ruclips.net/video/Nt-qa_LlUH0/видео.htmlsi=bvcDZ-ET88oZeT_R
"Dynamic this" solves an Expression problem though. It would be a disaster to simply remove it. An alternative object extension mechanics would have to be provided before that.
Slight correction in your event handler, "this" is the same as event.currentTarget, not event.target. The target is the element that was clicked on while currentTarget is the element with the event handler.
In some cases, such as this one, it would be the same, though it's definitely an important distinction to keep in mind.
yeah, just to make it a little clearer:
(i) event.target is the node where the handler function was written
(ii) event.currentTarget is the node(parent) where said handler function bubbled up to - where event currently is being handled.
@@redsnflr Not sure what you mean by where it was written. The handler is called (I think you may have meant this?) when the element, or descendant of the element, that the event listener is registered to is clicked (if it's a click listener, as is the case here). If there are no descendant nodes, or if you just click somewhere in the parent where the child is not, e.target will then equal e.currentTarget, ).
If anyone wants to better visualize it, just search event propagation for some easy to understand diagrams.
@@phillipandrew87 yes, where it's "handled" is where you write the event handler function, e.target is static but currentTarget is dynamic based on where the event currently is.
@@redsnflr Okay, I see what you were saying. By the way, just so no one who reads this gets confused, e.target is dynamic, e.currentTarget is static.
i think that calling things AFTER defining them makes much more sense, I get super confused when the file doesn't have to respect a specific order... and seeing that so many people do terrible crap when they are not forced by linters or interfaces like typescript, I think it's very much needed to adapt to these better practices
On a real production project I almost certainly will have each of my functions in a separate file (excluding anonymous functions and callbacks) and when passing callbacks I usually want to bind the parent context like it is default with arrow functions, so I'm the opposite: I use the function keyword only when an arrow function does not cut it. Which is rare.
Yeah, the example util functions given are great examples of functions you'd never even have in the same file as where they're being used in the first place. Sure, having the functions below the main logic of the file makes sense, but having those functions in a different file entirely makes even more sense. At which point using function keyword vs arrow functions don't really matter in terms of readability anymore.
One of those rare cases is when you want to use the arguments keyword!!
Like, you made a callback, but there are no docs, so you print out all the arguments of the callback, this doesn't work with arrow functions sadly
@@arjix8738 any cases where you could not just use the rest parameter?
@@ZakiWasik it's a matter of preference, I prefer arguments when the arguments are unknown
Reason 1 is also why I use arrow functions. Not out of puritanical belief or anything, but the backend language I work with the most is F#, which requires everything to be declared before it can be used. And when writing functional Javascript (or especially Typescript), the languages are actually extremely similar and I think it's the best functional approach. F# enforces order of files too, which can't really be done in Javascript, but I wish it could be.
Thanks for sharing Kyle. I prefer to use the utils file to store the helper functions and import it to the main file.
depends on the size of the app and how often you're going to reuse the helper functions.
Why would you define the utility function in the same file you call them ?
Not all functions are utilities beyond 1 file.
I think arrow functions do not require context switching, I may be wrong. Thus for small snippets of code I prefer using arrow functions and for larger snippets I use normal functions. As for organizing code, whether I write code at top of my file or bottom doesn't matter to me that much due to modularity, I do not write any thing else in the main script rather one main function and then calling it. But that's just my style. Honestly I do feel all the rules and guidelines for writing clean code is meaningless if your code is not performent. Most of the time this leads to unnecessary abstruction that often have many unnecessary instructions that are not needed but still called only to keep the structure "clean". For example, looping over same array multiple times in different functions where everything could be done in a single loop causing much less memory access (one of the biggest bottlenecks). Javascript is not a compiled language, but and interpreter. So from compiler diesign perspective, the optimization done by jit compilation is no where near like languages like c, where compilation in release mode throws away all the fancy abstruction and completely reorganize only performent code. Sadly dueto the dynamic nature of js and being and interpreted language this is not possible. So developers should be mindful of the cercumstences. However again it depends on how performent one wants his code to be. For a dataview kind of website it doesn't matter, but for things that requires high amount of computation it matters. As an example, working with canvas 2d if you floor the arguments before passing them to the function, you will see a significant boost in performance. The reason is simple, interpreters are not as smart as compilers when it comes to optimization.
The point I want to make is that function calls have costs .
Ok, so now I have two things I disagree with you: not using semicolons, and now the arrow functions :P
To me, having to define the functions before they're used is not an issue, but a plus. It helps when you work on a team where usually a few devs are messy with their code, so these small things that force you to be a bit more organized are really helpful. Same goes for some people's neverending creativity for using 'this'. With arrow functions we avoid several errors that cause bugs. So in the last few projects I've worked on, we use the opposite strategy: everything's an arrow function except for some specific cases.
As for the syntax, it's just preference/getting used to.
Anyways cool video, it's nice to see different approaches / trains of thought.
WDS has some hot takes and I think he's doing it for the controversial comments and views. Almost every short I've seen from him is just objectively bad, but it drives a lot of views and comments. Most of his project tutorial videos have much better information, but the individual "why I don't use X" videos blow. His "why I don't use the useEffect hook" video is a golden example of a really awful take for no reason other than rage bait
I think for react is more cool and clean code to work with arrow functions with const/let, because you won't doing any hoisting since your state and stuff is being defined at the top of your component function, and any helper/handler function as well don't need to be hoisted
@@Issvor Assume mistake over malice. I don't think he intentionally does it for rage bait; I think he's just mostly a self taught and solo developer who doesn't have all the information.
@@IceMetalPunk That's a fair point
I haven't seen this useEffect short but I personally put a lot of effort into avoiding using useEffect due to it's re-render strategy and awkward handling. However, I don't avoid it at all costs. Sometimes it's the perfect (or only) tool.
It seems to me that almost everybody uses arrow functions for the same reason: to give a structure to their code. It's like telling a story without giving spoilers.
this video wasnt much much about syntax but more about logic. this was actually awesome knowledge that you gave. thanks!
as solo dev its okay but when you work with code that someone else wrote, hoisting is pain in the ass
because in comparison, if there are no strict rules where we should place functions, hoisted functions is immediate "peek definition", because they can be lower in file or higher, whilst arrow functions enforce you to define them before using, that makes them not significantly easier but quite a bit, also no "this"
after dealing with class components in react i truly started hating hoisting
I hate this...
but I love this comment
I agree with Kyle here and use normal functions for helper functions and arrow functions for callback functions. It's much easier to identify a function this way, plus hoisting is a bonus.
Love your channel, man. I love that your videos are concise and straight to the point. Learn a few new things everytime I watch your content, even if it's a topic I already know well and you give me a different perspective on it.
Why do you want hoist arrow functions, they're introduced in javascript for the specific cause. I don't understand the argument here.
Yeah. It's like saying "I don't use Typescript because it's more work". Correct (in a sense), but that work is there to actually make the code less likely to throw errors along the way, when the project grows much bigger. Hoisting is ok for small script and such, but I would avoid it as much as possible if growth is expected.
Also maybe I'm weird, but I like the arrow look, especially with no parameters it looks like it's taken from an ancient occult book lol
He never said he wanted to hoist arrow functions, he simply said why he uses one over the other. Those are two different statements
@@firedforfighting I wrote what i understood from the video, but I side with arrow functions coz I want errors to be thrown at development stage and not at the prod stage if they went unnoticed while using regular functions.
The main reason I would use const arrow is the fact that they can't be modified. If you do (with a function) formatNumbers = [1, 3] somewhere bellow It would "destroy the pointer to the function itself".
Basically you should prefer not to mutate almost anything unless it's better for a specific case for some reason (readability, performance, can't do otherwise, etc). So mutating a function should pretty much never happen - whether you define them with function or const
@@BritainRitten Right, and being able to define a function as const enforces that.
@@IceMetalPunk If you need to enforce the idea that you shouldn't be mutating a function reference, then you almost assuredly have far more serious problems within your team...
@@BritainRitten how do you mutate a function ? lol
@@soniablanche5672 maybe by just declaring it again
I thought I was alone with this concept. I hate using const over function. Most of the reasons you said but primarily because when I'm scanning code for a variable or function I don't want everything to look like a variable. And hoisting, I don't want to worry about where I'm defining my function.
The funny part is it's not even really any shorter of syntaxes. Const name () => is is literally one less character than function name() . You can omit the brackets in arrows but I often use them anyway.
You make a lot of good points there, especially the ReferenceError which I honestly hadn't come across yet, because I work with nested functions almost exclusively. Maybe it also has something to do with the fact that to me as an old C coder defining a function before use is as natural as breathing.
The reason why I love arrow functions so much is because unlike all the syntactic sugar around functions, classes and methods todays programmers grow up with, assigning an arrow function is very close to the bare bones of functions, which, when all's said and done, are very little but an address to jump to in memory.
I must say, I disliked JavaScript for the longest time for its lackadaisical typing and conventions, but ever since I began looking at it from the bare-bones perspective, it has fast become my favourite language, even before Lisp and my beloved C
Yes even I didn’t face in react but maybe its issue in vanilla javascript I use it still I have a habit of writing function in order then call them at the end just like other programming languages 🥲.
do you use Typescript given your JS typing issues?
@@redsnflr Funny you should ask. It took me a while to discover TypeScript, but I instantly fell in love all over again 😉 Honestly, it's not "proper" hard typing, but that's what makes it so interesting - it holds a mirror up to your coding habits showing you what hard typing made you take for granted.
Good points, but this convention breaks as soon as you need to type a function in TypeScript (think of FC). Plus, I've found that relying on hoisting generally results in poorly organized codebases unless you're working on a tiny project w/ a single file (where arguably convention wouldn't matter that much anyway). If you think "what if I want to run some code in a utils.js file where I export my helper functions?", then I would say look back at your architecture and think whether you really want to run arbitrary code in a utilities file that's meant for "utilities". Idk, these are some of my reasonings to use arrows everywhere (except in OOP & decorators). Everyone should use the approach they feel most productive in as long as they know the differences between them 💙
I actually hate hoisting lol, and my helper functions are always in a separate file anyway. But it’s all about taste in the end of the day
In short, use arrow functions only for:
1. anonymous callbacks
2. event handlers
I completely agree.
I don't use arrow functions with const/let but didn't even think why. Thank you for telling me why 😂
For reason 1. If I have many helper functions and especially if I want to use them in many different scopes or in different files. I like to have them in an object, possibilty in a separate file that can be imported. This way, I have a structure where I don't have to scroll past the function expressions all the time as I can keep them in a separate file or collapse them all together, and this works really well with arrow functions. But it really depends on the complexity of the project naturally. E.g.:
```
export const helperFunctions = {
helper0: () => {
console.log("I help")
},
helper1: () => {
console.log("I help too")
},
helper2: () => {
console.log("I help three!")
}
}
```
Your use of hoisting is what the Clean Code book teaches. It kinda reads like a newspaper article where the important stuff is on top, the more you go down the more details you get.
For example if I'm going to explain how to make a pepperoni pizza, I can say:
"Roll the dough out, spread tomato sauce, grated cheese and sliced pepperoni on top in that order. Then put the pizza in a preheated oven on 200 celcius for 30 minutes. Slice the pizza and eat when sufficiently cooled down."
This is already pretty verbose but technically for most people this is enough to know what we're making and how. The "helper functions" would then in order that they appear underneath the main function. So in this case:
"The dough is made by..."
"The tomato sauce is made by..."
"You grate the cheese by..."
"The cheese is made through..."
"Slice the pepperoni in thin 2mm..."
"The pepperoni is made by..."
"The pizza is sliced in 8 different equal parts"
I could put the oven preheating details also in it's separate section but making it too generalized actually takes away descriptive power. So it's important to keep track of your level of abstraction, don't mix the different levels too much and don't go too deep that you get lost.
When you open the file you immediately see what the code is doing. You scroll down to see how it is being done exactly.
You make a good case, but you stretch the analogy too thin. Ideally, you wouldn’t have your functions lain like that in a single file to where they can result in this issue to begin with. That, in my opinion, is bad code. Trying to remedy that with hoisting is not clean code, it’s bandaging some (likely) not-well-thought-out code organization.
More so, your analogy can be used to derive some benefits for the arrow syntax. With hoisting, if you end up with the scenario in the video, functions that compose or use each other need not be declared in a meaningful or logical order. Arrow functions force you to order your functions from the most self-contained to the most complex. This way, you are guaranteed to find that the steps for making a basic pizza dough are placed strictly before the steps for a mozzarella-stuffed dough, and not jumbled anywhere else. THIS reads more like a recipe book.
I use function expressions at work because that's what's used there and it's not important enough to rock the boat. But I really dislike them in most cases. I find regular function declaration syntax much easier to read. I use arrow functions a lot, but as in the video, mostly when defined inline as a callback, or if I need to close over `this` (very rare). Hoisting is sometimes annoying but mostly not an issue since most of my functions will be in module files rather than defined where used.
A lot of people commenting about putting helpers in another file... A couple things:
1) Definitely do that. I think Kyle already knows that's best practice. But for the sake of brevity, he makes his point here not mentioning it.
2) If you DIDN'T do that, and kept all helpers in the same file, I think what Kyle says makes perfect sense -- important logic at top, function definitions below.
3) Either way, for DECLARING functions, I agree that the traditional function syntax is clearer -- yes even when declaring them in separate files/modules.
4) Arrow functions are awesome, but 99% of the time I use them I would agree with Kyle here -- it's in the context of anonymous lambdas.
I had the "this" problem two days ago and could not understand why the arrow function didn't work, and the function did. Thanks for explaining it! I ended up just telling the linter to ignore my function, lol.
I know about hoisting but I don't rely on it. I write regular functions as much as possible on the "top-level" to take advantage of the `function` keyword as you mentioned, and at the top of the script so that it "flows" naturally
Wow. Awesome to finally see a Kyle video I don't agree with after many years
If you use typscript like almost everyone else, then that means your code will be transpiled into es5 anyways, hence your functions will be actual functions regardless of the declaration method and be hoisted anyways. i got your point tho
To me, hoisting is one of the most terrible features of JS, and it should be removed and burned. The idea that your code can reference things that you haven't even defined yet is just asking for spaghetti code. Removing the possibility of hoisting is one of the biggest reasons *in favor* of arrow functions, in my opinion.
Module imports can clean it up if you don't like scrolling through the definitions to get to the main logic.
I always default to arrows unless I need to create a new context. I'm not bothered by functions clogging up the top of file because they probably belong somewhere else if you have that many of them.
Finally now I'm not alone with this opinion
When you use typescript, it doesn't matter if you use arrow functions or functions, it wants you to declare them before calling them.
My preference is to use arrow functions only where there's an immediate return, or if I need the outer this.
`function a(b) { return b+1 }` is less typing than `const a = (b) => { return b+1 }`, but more typing than `const a = (b) => ( b+1 )`.
In general, this allows the reader to quickly make assumptions about the code - if you see `=> {`, you know to look for a `this` referencing the outer block
thank you so much, videos like this one (efficient, dense, clear) help me fill in the significant gaps i have in my knowledge
I am a Vue dev and in Vue 3 I exclusively use arrow functions. I a helper function is required at the top it's placed in a file of it's own. I prefer to group blocks based on what they do rather than just put "important" functions at the top.
I prefer function keyword because it is clear that it is a function, not a const variable. Readability. It gets confusing when everything starts with const.
The people in the comments trying to refute the first point of the video are forgetting one thing: In a team, one programmer should avoid making the dreams of other programmers impossible.
In some cases (especially very small libraries) it totally makes sense to put the public API at the top and less important functions at the bottom.
WDS is the mentor we all need.
Definitely the most important reason for understanding whether to use ES5 or ES6 function syntax is with 'this' binding, especially when it relates to creating methods. That is actually important for the functionality. While I appreciate and understand your 'main reason' for better layout flexibility with hoisting, it is simply personal preference and isn't as important imo. Either way, thanks for the reminders. 'This' is and will always be confusing forever.
You last frase defined me. Imagine learn "This" in a language that isn't you native one. It's so confusing 😂
Haha, good thing we're mostly past using `this` in JS these days since there's a much bigger focus on functional programming. I don't think I've used `this` for years since when I did jQuery stuff. And I'm happier for it.
I prefer to read a function definition first and then I look up how it's used,
so the arrow functions don't pose a problem for me.
As others have said, the flow of code as is executed is generally first defining things and then using them, so having functions before executing them makes sense. Now it’s fine to have a different preference but you can’t escape the reality of how code is executed entirely. If you import a function from another file, for example, it has to be at the top of the file. At best you can partially change the order by utilizing hoisting but not entirely, so you still end up having to jump around a file in certain cases. As someone who values consistency I find it much easier to simply go with the flow of code execution and generally expect entry points to be at the bottom of a file.
Then there is the whole thing when working with a team and/or an existing code base, you generally will want to match the style of the project, so always keep that in mind. :)
Not to mention that defining your helper functions as arrow functions can usually make them much more compact (if they can be written as one expression) and make scrolling through them much less of a big deal.
As a react developer I always use arrow functions, but examples in this video is cool, it's good to know this stuff
Personally I like definining react components as `function`. E.G. `function App() { return }` rather than `const App = () => { return }` (assuming you have some logic in it). However, the benfit of arrow functions in React can be for TypeScript typings, like `const App: React.FC = (props) => { return }`, but I find these explicit types unnecessary since the implicit ones are IMO just as good.
But I've used both styles, and at the end of the day, the most important thing is consistency within a project, and harmony with other devs :D
This is really helpful. I am always trying to find ways to use arrow functions. You make a great point here. Thanks.
Thanks for this. As a tech lead I use your entire channel to teach the “Dunning-Kruger Effect” and this video expands the syllabus.
Most of the concepts in this channel are just personal enlightenment. And that's one of the reasons I don't like RUclips. There are some good channels but most of them are crappy. And also, using hoisting was a bad idea from the beginning. It reverses the flow logic and overtime makes things messy. These channels always rely on small code pieces. You can make everything right with a small code piece. The issue is to make it valid for huge repos.
I just watched the intro part and I'm already sold. 😊
arrow functions inside functions (no "this" hoisting needed) & normal functions in the global scope is how I generally do things.
i m a full stack developer.. I know this concepts.. but refreshment of this concepts and
the explanation in your videos gives my mind a kind of comfort and boosts confidence for unknown reason..
keep up the good work friend.. your video was inspiring for me to keep working as dev !!
I discovered THIS the hard way during a implementation of a binary search class object. It was quite interesting.
1) Avoiding hoisting is a good thing. It's not a difficult concept to understand but one that has generally only added confusion and errors in JS. 2) If none of those functions are important, then why were they written? The example here is a case where it is both too trivial to support the argument AND a more complex example would be better done with modules, as others have noted.
Amazing! It's nice to see an expert writing standard function syntax for the exact same reasons I also do.
I’m almost always dealing with other people’s code right now so my own preferences are pretty mercurial, entirely down to how I’m feeling on whatever small project I’m working on. I’m usually consistent within a project, but across projects it can vary.
I think I usually use regular functions when just defining them in a module because when I’m naming them arrow functions don’t save much if any typing. That’s about it.
This is a based take
So you write garage code?
I devide my code in sections, one being helpers functions, all declared with arrow functions.
Later I have one update function, which all actions go through, so I’m never in doubt whether I’m looking at a helper function or the core of it, because there is only one core update function. The rest is helpers and sometimes i move to another file and have them all imported. Nice and clean 😊
im intrigued, can you put a small example on codesandbox or something?
Never thought of functions this way. Thank you!
That's a good reason, I also like to have details of implementation at the end of the file below everything else. But there are ways around functions declaration (is that a right name for using function keyword?).
When (if) you use react components you can just put helper functions at the bottom, as the component will be ran later than those, so they will exist at that point.
Also those helper functions can just go to a separate file (which they probably should).
So I usually still use const/let functions.
Thanks, kyle
It was a great comparison
Great vid, I’m an sdet coming from c# and transitioning to Js, your vidz really helped me
1. Use function is more semantic
2. There is no need to use the arrow function to define the functions always in modern JavaScript or TypeScript, especially if the bundle file is not concatenated directly.
3. Because of the scope of the variables in the function, the use of 'function' is clearer.
4. Readable and Maintainable...
IMO, helper functions should always come first, it doesn't make sense to use things which aren't yet defined. And if it's clogging up your file, extract them into a dedicated file.
Everyone is entitled to their opinion, and if this works for you cool. But if code like you've written were to cross my path professionally on any team I've lead it worked on it'd get kicked back from code review. Hoisting can be a pain to debug if something goes wrong. And while you might not have a problem a jr dev who comes in behind might not be the same.
Hoisting is a problem regardless of experience because it can lack reasoning why hoisting and not a constant arrow function was chosen.
This is why I don't like JavaScript (especially in backend). Billions of ways to do a single thing is a double edged sword. Sure it allows more than one way to do a task. However, it adds unnecessary complexity to the codebase.
Makes sense! I knew the fact but never really thought about it until now. :)
Interesting take. Like a lot of the commenters, I define/declare functions at the top whether using the function keyword or arrow functions. I'll even look at my code below and go back up and cut/paste the functions in the order in which they are called. It just works with my brain that way. But I think one advantage to putting your "important code" at the top is that once the functions are written and tested, you might argue that there is no need to see them because when writing the "important code" and using tested/proven functions, you don't need to be concerned with the implementation. However, that is one of my issues. I always concern myself with the implementation. Slows me down sometimes. 🙂 Another thing I will say is that sometimes it takes a second to see whether something is a function or a const variable if they are all bunched together so it becomes more important for readability to use white space properly and have some order to defining const someFunc => oneliner; vs const someVar = value;
Yea totally agree with all points👌 after my initial arrow function hype I moved back to normal functions in many cases
Another reason some might prefer regular functions over arrow functions for callbacks is that you can name an anonymous regular function. Makes it a bit easier in a stack trace to quickly see the source of the error.
Personally not for me, but I did occassionally find it useful when I had to write IE-compatible code back when callbacks were king and promises (let alone async await) weren't around yet.
Thank god those days are gone.
you do realize you can do anonymous arrow function right? (() => { })()
Hosting, very much like 0 type safety, is what gives us developers the freedom do things that causes bugs and/or confusion without any real benefit.
The reason you mentioned why to *not use arrow functions* is the exact reason for why I think you should use them.
Having a file with "a bunch of nonsense" at the top which you have to scroll by to get to the meat of it all is indeed not suitable. Therefore these helper functions shouldn't be declared in the same file as they are being used in and rather be imported at the top.
Inside my React components I use arrow functions to implement event handlers and inner functions, I rarely found myself relying on the 'this' construct. But I think it's ok.
At work we just use modules for commonly used helper functions and import them. For things like onClick functions we use arrow functions defined at the top of the react file underneath the useState declarations.
Thanks for excellent video and Happy New Year!
Also, I refuse to let functions that have no business having a "this" pointer to have them. I will bother with extra syntax to say as much.
Woah! Thank you for this!
This is really a personal preference situation.
My brain likes consistency. It’s so difficult for my brain to process differing syntax for the same thing. If I have functions and arrow functions in the same code, then I start to loose track of what’s going on and have to put in more brain power. Its much easier to see => and know that what I have is 99% likely to be an arrow function.
For context: I used to be an avid function hoister whenever possible.
Context Edit:
1. I don’t used “this” often
You just introduced OOP thats great you are learning.
I mean... if you're putting all of those helper functions in the same file as the "actual" important code, maybe the function syntax isn't the problem.
But I agree. The "function" keyword is better to read than a const + arrow function.
in the arrow function, 'this' always refers to the main window whereas in the normal function 'this' refers to the document or the element to which the event listener is added.
My rule is high level functions are in the form of named functions, while anonymous functions are arrow functions. Oh and no single letter variables outside of for loop indexes. Readability and maintainability drive the choices.
Thank you! I 100% agree.
Use => for callbacks and single liner codes without { } and return.
const sum = (a, b) => a + b;
Abssollutely. Many devs make hype instead of correct usage
I tend to opt out of code that can mutate outside state by default. Using arrow functions/ closures that automatically capture state outside of their defined scope can open doors for silly bugs.
I assume you've never worked on a massive code base where you end up in scope hell from legacy code you or 20 other developers wrote. There is a place for everything, and let and anonymous functions are a godsend.
Usually helpers grouped in some Object thus you will also have an error about initialization. Try to use hook document.load.
I swear people choose weird hills to die on. Just pick one and stick with it. Extra points for using modules to make it nice and clean.
If you have helper functions, I would maybe share the main code in smaller pieces, so you can put those functions into their own files and then use it on the main code.
Inner functions are where I'm most conflicted at. If I'm writing closures, I'll write the inner fn in the regular syntax.
However if it's a fn that is used as a callback in e.g. event listeners and I'm taking it out of the function call for whatever reason (e.g. making the code read cleaner), I'll write it in the arrow syntax instead
If the inner fn is a one-liner, I'm more inclined to write it in arrow too regardless of what I said above, to save on the curly braces and the explicit returns
Kyle, have a great 2023!
I always prefer arrow functions. Only in classes it is not allowed.
Great example! 🧑🏼💻
Just put all your helpers in a file and require the file at the top. If you use the helpers often make a npm package for all your projects.
There's a mistake in the thumbnail code -- iDislikeThis should either not have the curly braces (which would cause the result of a + b to be returned implicitly) or else it needs the keyword return before a + b.
I agree 'function myFunc()' is a lot nicer looking than const 'myFunc = () =>', it's not even shorter which is the main point of arrow functions
I prefer the syntax of the normal functions. That's the main reason for me.