functions are also objects in javascript with their own methods like .call() or .bind() - so another way to declare a function is creating a new instance of the Function Class like: let add = new Function('a', 'b', 'return a + b');
Every function can be used as a closure, so the only difference between arrow functions and ones with the function keyword is the this keyword having different references.
@@Flexximilian That is the extra references that the non arrow version carries with it. Both are very memory intensive and it is best to not use either of them in loops and you should pass references into the function that is defined out of the loop for even better memory management.
This was really good! As a casual JS programmer (but very experienced in other languages), I have found this topic to be very confusing. Clear and concise explanation of the topic. Thanks!!!
I primarily use Function declarations as well. But that use case for using arrow functions inside of a class is excellent 👌🏻. Very good tutorial and example of when arrow functions really add value!
This explanation was on the point. I als way struggle to explain others, why "this is the way" for JS. And there always pop up the question "why don't they just change the way, JS functions works?" Well, this would hurt old code. Things would stop working or could start work in a strange way and the dev. Would need to figure out, why the website won't work in the real user's browser, but in the old IE6 of the client.
You can benefit from naming your functional expression functions so they show up with a name in stacktraces. If there was an error in this function, it would show up as the add function and not just another anonymous function. const add = function add(num1, num2) { return num1 + num2; }; When I explain fat arrow functions automatic scoping of this, I show them the bind method used previously, and how that worked, and how with fat arrow functions you no longer need to do this. But if you're in a place where you can't use a fat arrow function, that function.prototype.bind method is still available to add the necessary scoping into an existing method.
Really interesting, thank you both! I was aware of the hoisting difference but the lesson around how the “this” keyword gets affected was new to me, and really well explained!
I definitely need to up my JS game ... and stop relying on jQuery quite so much... I'm really enjoying the JS vids (and the little JS sprinkles in your other videos) so please keep 'em coming 🙂
Anytime I can only find a jQuery example for a solution I only use it as the model to write my own plain vanilla es6 version. It's the same with html and css. I just wrote out whatever I need by hand. I hate frameworks. I can replicate the one or two things I might need from any framework without having to install twenty seven dependencies, pay a licensing fee and hire a consultant to help me integrate. But that's just me. I started writing programs when I was eleven on a TI 99 and quickly outgrew it and moved up to a C64. I was making my own pixel by pixel graphics and animations in basic and Cobol on a command line in 1982.
I certainly have my bias, but i strongly believe being in the const-first camp holds even more water (figuratively) when working with arrow functions. Except in specific edge cases, reassigning function expression variables is a sign of code smell, imho
Good tutorial for beginners. He also had some great things to say about order of operations stuff (variables, then function declarations, then invocations, then rerurns). In fact, I wish he had mentioned using "Early Returns" / "Execution Guards" at the very top of the scope before the variable declarations. To his point about when to use which style of function: don't do inline multiline declarations -- like, ever; if it is multiline then it is complex enough that it deserves to be pulled out and named as it's own operation. If not, then you're not writing Defensive Code. If you're not writing Defensive Code you are inviting corruption. That even goes for multiline if/else blocks (or loop blocks). I know we've all been taught to "always write if/else code as blocks" but you should virtually never do that. If it's more than a one-liner it has enough complexity to need be pushed into a function with a proper name, otherwise it will without a doubt become a heinous mess almost immediately. Lastly, he never mentioned writing a `new Function`. In rare cases it is the only way you can do certain things. Be very careful with that one tho because it behaves similar to `eval` which, no -- it's not "evil", but if you don't know what you're doing you can open yourself wide open to an XSS attack. Good tutorial for beginners tho 👍
1:57 you would add the name there otherwise it would be an anonymous function. If an exception was thrown you would t see the variable name the function was assigned to, rather you would see anonymous function. You might want to reassign different functions to that variable in some sort of strategy pattern… if an error is thrown, it’s useful to see the name in the stack trace error to quickly find the problem.
If you have a lot of functions, consider using import and export method to split the functions into separate files. This will make your code cleaner and much easier to follow.
That bottom 'Another arrow function ' code screenshot on 00:22 actually contains a mistake: when you use an arrow function without curly braces, it means the function has implicit return. In this case adding 'return' without {} will throw an error. Correct would be: ... => num1 + num2;
That was awesome, Kevin & Chris! I've had this on my gotta watch list since it came out. It was just the right length and covered just the right stuff. And I learned more about the unique nature of 'this' in the context of arrow functions. I had known about hoisting, but Chris' explanation of it really drove it deeper into my brain. And I'm so glad you asked the question about his preference for code structure as that popped into my head right before you asked it. And I was relieved to find that I do it the way Chris does (but then, I'm old too...a lot older than Chris ;-)). Thanks again!
a guy i know work for a big tech company and they got mad at him for using arrow functions, they said let that = this was the industry standard way of writing code! he reluctantly agreed for fear of repercussions
This is great! Thanks Kevin. I really liked hearing from Chris Ferdinani. You two explain JavaScript together very well. I do not see the link to Chris Ferdinani's site so make a big button for me please.
There is a good use case for function expressions. Scope. They follow the scope definition of the variable they are assigned to. Arrow functions similarly, but personAlly I like to be explicit and make it clear a function is just that. Arrow functions are easier to misread.
i literally just now searched for Kevin Powell javascript thinking you had this type of video, I was looking for why the arrow function is important and now this gets recommended. damn
I've never used function expressions or anonymous functions. I generally use function declarations at top-level, but arrow functions inside other functions
hoisting is done at compile time only. simple as that . function expressions are done in execution time and it can implement dynamic functionality so the reasons for choosing one over the other is more than a subjective preference but it's a question of design. Do you need run time logic? mostly not
The reason is "syntactic sugar". Function declarations were provided to give a Java-y feel. Function expressions is what actually happens in JS/ECMAScript. Arrow functions were introduced as short hand syntax (brought over from CoffeeScript that has both "fat" and "skinny" arrow functions), and whose syntactic sugar is to bind "this" automatically.
Awesome! Much needed. Please create more videos on GSAP ScrollTrigger and SVG animations, Lottie animations. All combined into one series. That will be great.
In regards to his comment at about 1:50 you would name your function in the below example because that name would return in a stack trace and help you understand what function is failing instead of it being anonymous. const example = function add(numA, numB) { return namA + numB; }
While this is historically true, engines now show the name of the variable to which the anonymous function was originally assigned. :) For example, if you'd drop the `add` in your code, the stack trace shows "error at example". (I just tried it out on Safari, Chrome, Firefox, Node and Bun, just to make sure)
Thank you Kevin! I really need more basics .js a lot of times on workshops they teach functions and stuff but not the basic logic behind. Hope to see more content cured by you!
There's also a 4th way to write functions, though this only holds true as methods (within objects or classes). As a method, the add function can be written as `add(a,b) { return a+b; },`. If defined within a `mathematics` object, it could then be called using `mathematics.add(3,4)`
This is awesome. Personally struggled with the whole hoisting concept and arrow functions in javascript as a beginner. Still does to this day lol. A great part 2 vid idea would be explaining event listeners. Specifically, the difference between: form.addEventListener('submit', submitHandler); vs form.addEventListener('submit', function(e){ submitHandler() }) And form.addEventListener('submit', (e) => { submitHandler() })
the difference between them is exactly what this video talks about: the different ways you create functions. addEventListener is not doing anything different in your examples, you're just specifying the callback parameter in 3 different ways.
@@rossclutterbuck1060 I probably should've said explaining callback functions within event listeners and not just event listeners themselves. Going over subtle differences and why you'd use one over the other in a beginner-friendly way would still be useful. The second example lets you pass a parameter to submitHandler() because it's inside an anonymous function, while the first example does not. That might seem obvious to those more experienced with javascript, but can easily trip up those starting out.
He briefly touched up on that when he said `this` would be assigned to the caller of the function. In your first two examples, `this` will be the form that triggered the handler, while `this` would be the window object (or undefined, if the code is inside a module).
Naming the function in a functional expression lets you see the function name th the stack trace when debugging. At least that used to be the reason to name them. I haven't used that pattern in a long time.
One of my biggest complaints about ES6 was all the new syntax for objects, classes, and functions that wasn't required. It was just sugar. There was also sugar for promises that I was happy to have...
1:40 - The name is sometimes added because debugging JavaScript code in browser is an absolute disaster, in my opinion. Imagine you have a mutation observer that automatically sets some event handlers. Imagine the event handler threw an exception, because of some reason. Instead of looking into an inside an , you look into the function and then the . Oh, and when the code is wrapped in an onload event, that adds even more to the confusion.
What happens when you assign a function declaration to var instead of let? Another good reason to use function variables is you can pass a function into a function. e.g. callbacks.
There's an implied return in bracketless arrow functions. Removing the brackets from the arrow function changes it from void to returning a number. Doesn't make a difference here, though.
.bind creates a new function that wraps the first. This is technically less efficient with memory and call time, but practically makes little difference.
The really cool thing about function expressions is that they can be reassigned during runtime. Imagine that you want to assign a function based on their handling of a particular language where the language is not static during runtime, such as processing data that contain strings written in one or more languages for example.
you can actually reassign any function that is not explicitly a function expression stored in a const variable independent of if its a regular function declaration or function expression!
Yet another edge case: when you have a function written with FE approach through var and it’s called before initialization, we get a different error as opposed to using let keyword.
Function expressions in other languages will assign the return to the variable and not the function itself, I am certain that this isn’t known as an expression in JavaScript and that it is just an anonymous function. But this is JavaScript and they name expressions wrong, just look at a language like Rust and you will see that expressions always assign values based on evaluation and not assign the reference to the function, this would be a statement as the value isn’t returned. Using an immediately invoked function would assign the value and not the reference. Once you learn more languages you wouldn’t use the term of expression to describe what is actually being defined with that code, just a heads up for learning other languages.
Just to prove a point, try this let x = function y(z) { return z; } and see what happens, you will be able to call x(“test”) which will return z. So, is this an expression or a declaration? This is the very reason I find this use of the word expression misleading. You will now find that y is undefined and that x is a function named y! Just try this in the console and you’ll find that when x is evaluated it will show a function called y that you can’t call.
What’s up with using let everywhere? Is he going to be reassigning all of the functions he was assigning to variables? This would be so confusing, whenever I see I let I start searching for the reassignment.
exacly, people should use const more, and use let only for variables that actually change value and don't get me started on the ones that use var for everything 😂
Also, let and var should be used based on whether it is needed only inside or also outside the block where it is declared. Avoid making everything global, keep it inside where it is needed to be used. Especially utility variables inside a function, loop counters, temporary vars, placeholders, etc.
Another 'benefit' of function expressions is that you can dynamically re-assign a different function to the variable at any time. So you could dynamically change what 'add()' actually does. Sounds bloody dangerous to me, but anyway.....
unless you're using TS, you can override a function at any time. this is all valid: function f() {/* do something */} function f() {/* do another thing */} f = function () {/* do yet another thing */} The first two will be hoisted because they are function declarations; the third one will be evaluated in order because it's an expression.
It’s not exactly personal preference. You definitely don’t want to use expressions to declare “methods” (doing it this way makes it not a method) on a class. If you don’t use regular function declaration syntax it won’t be on the prototype and every instance will have to recreate it.
Shouldn't all those lets be consts? It almost never necessary (and almost always bad practice) to update variables that contain a function. My linter would go insane 😅
I love your videos Kevin but that thumbnail triggered me because it's wrong. The last example... let add = (num1, num2) => return num1 + num2; ...will trigger a syntax error. You need to remove that return or put them inside curly braces. It's either one or the other, not both. Either the ones below: let add = (num1, num2) => num1 + num2; let add = (num1, num2) => { return num1 + num2 }; If it was made on purpose to receive engagement, there, you got me. I hope not though.
You didn't even mention object and class methods. All JavaScript functions declared with the keyword (whether declarations or expressions) are created with a function.prototype property that's an object holding a reference back to the function as "constructor" and any other functions that will become class methods, whether they're ever actually used as classes or not. They can also be invoked with the "new" keyword, which can make zero difference or every difference depending on what the code does. Both arrows and class/object methods don't do that. They don't have the overhead of a prototype property and can't be invoked with "new." This is good practice to provide interfaces that can be used in exactly one way, to prevent footguns. Arrow functions have neither an inherent "this" property as you discussed, but also don't have an "arguments" construct. Any attempt to reference "this" or "arguments" from inside the function will use the lexical scope instead of passed scope. I have a typehinting library that uses "arguments," but otherwise this is useless overhead you can chuck with an arrow function. Rest parameters removed the primary use case for the "arguments" construct, for variable argument lengths. Class/object methods still have both, allowing call/bind of a specified "this" and arguments introspection. Hoisted functions are also treated as if they were declared with "var." This means A) they use function scope, not block scope and B) they can be _redeclared_. For that reason alone, it's useful to use arrows or function declarations with a "const" keyword; there's nothing like a nasty surprise of having a function get redeclared into a variable because you reused a name. var will happily allow you to redeclare a variable over and over again within the same scope; let and const will halt on redeclaration, and const will halt on any reassignment.
Please don’t use ‘let’ or ‘var’ to declare functions. Use ‘const’ instead. Const will prevent you from accidentally overriding the function declaration. let count = () => {}; and then you can do count = 5, which will break if you do count() later on.
My 3-cents: Terse code is harder to debug, harder to read, and harder to set breakpoints (debug). Also, arrow functions with implicit return statements and lean coding constructs may be convenient once you figure out all of these tricks, but they are a real pain to learn. That is to say, you don't really know what the code is doing sometimes if you don't know the "hidden" rules behind the syntax. Old school code is more explicit. It doesn't hide anything and you can figure out what it's doing just by looking at the code. You don't have to look up some "hidden rules", etc. to figure it out like you do with the newer JS syntax. Personally, I prefer verbose code and "old school" syntax (traditional constructs) because it's easier to read, debug, etc. For my coding adventures, I want to be able to set a breakpoint anywhere in the code without having to rewrite it. That makes it more maintainable, which the newer kids on the block seem to devalue or ignore altogether.
I just dropped in to say your thumbnail is wrong. a function expression would look like const example = function add(numA, numB) { return namA + numB; }
I'm so disappointed! Normally Kevin knows every insane poorly documented way of doing things but the new guy never mentions half of the types of function. Generator functions, syntax: function* foo(){} Async functions, syntax: async function(){} and last but not least the Function constructor! syntax: new Function() the explaination of "this" was nice but if you go there we also want "arguments" and perhaps the scope? Come to think of it, now that everyone insists that what was always called "arguments" should now be called "parameters" why are they called arguments if they are parameters!?
Feels wrong , just a JS video. I mean not even a little CSS ? Sorry dude but there is literally 1000s of other videos explaining on how functions work. 😢
let instance = this; was the most used way. Function.prototype.call and Function.prototype.apply where introduced later into Javascript to allow calling a function while also passing (overriding) this. E.g. function sayHello () { return `Hello, ${this.name}`; } sayHello.call({ name: 'Chad' }); // This will return "Hello, Chad" And later still Function.prototype.bind was added that lets one do e.g. this: let sayHelloChad = sayHello.bind({ name: 'Chad' }); sayHelloChad(); // This will return "Hello, Chad"
functions are also objects in javascript with their own methods like .call() or .bind() - so another way to declare a function is creating a new instance of the Function Class like: let add = new Function('a', 'b', 'return a + b');
Upvote this
@@stevenstraker5105don’t tell me what to do
Nice I did not know this good thing I checked the comments.
Keep the JS content coming please! You have such a great approachable way of explaining things to those of us that are trying to learn
I thought I'd hear the term "Closures" a lot here, but I guess that was outside the scope of this video. (Yes, pun intended)
Every function can be used as a closure, so the only difference between arrow functions and ones with the function keyword is the this keyword having different references.
@@jfftckTry both in a large loop (e. g. forEach-ing over a large data structure) and watch your memory...
@@Flexximilian That is the extra references that the non arrow version carries with it. Both are very memory intensive and it is best to not use either of them in loops and you should pass references into the function that is defined out of the loop for even better memory management.
This was really good! As a casual JS programmer (but very experienced in other languages), I have found this topic to be very confusing. Clear and concise explanation of the topic. Thanks!!!
I like this format. Please make more videos with Chris. He explains confusing things well
I primarily use Function declarations as well. But that use case for using arrow functions inside of a class is excellent 👌🏻. Very good tutorial and example of when arrow functions really add value!
This explanation was on the point. I als way struggle to explain others, why "this is the way" for JS.
And there always pop up the question "why don't they just change the way, JS functions works?"
Well, this would hurt old code. Things would stop working or could start work in a strange way and the dev. Would need to figure out, why the website won't work in the real user's browser, but in the old IE6 of the client.
Please do more JavaScript tutorials. This is the best stuff, always in demand.
You can benefit from naming your functional expression functions so they show up with a name in stacktraces. If there was an error in this function, it would show up as the add function and not just another anonymous function.
const add = function add(num1, num2) { return num1 + num2; };
When I explain fat arrow functions automatic scoping of this, I show them the bind method used previously, and how that worked, and how with fat arrow functions you no longer need to do this. But if you're in a place where you can't use a fat arrow function, that function.prototype.bind method is still available to add the necessary scoping into an existing method.
Really interesting, thank you both! I was aware of the hoisting difference but the lesson around how the “this” keyword gets affected was new to me, and really well explained!
function declarations so straightforward … easy to
Read and understand
I definitely need to up my JS game ... and stop relying on jQuery quite so much... I'm really enjoying the JS vids (and the little JS sprinkles in your other videos) so please keep 'em coming 🙂
A lot of jQuery found its way into the JavaScript Browser API so feel free to drop jQuery. You don’t need it anymore :)
Yes, jQuery hasn't been necessary for years and it bloats the code unnecessarily. So take the step 😉👌
Anytime I can only find a jQuery example for a solution I only use it as the model to write my own plain vanilla es6 version.
It's the same with html and css. I just wrote out whatever I need by hand.
I hate frameworks. I can replicate the one or two things I might need from any framework without having to install twenty seven dependencies, pay a licensing fee and hire a consultant to help me integrate.
But that's just me. I started writing programs when I was eleven on a TI 99 and quickly outgrew it and moved up to a C64. I was making my own pixel by pixel graphics and animations in basic and Cobol on a command line in 1982.
@@PhilLesh69I am with you on this 100%. A bit older than you, but similar background. 😊
I certainly have my bias, but i strongly believe being in the const-first camp holds even more water (figuratively) when working with arrow functions. Except in specific edge cases, reassigning function expression variables is a sign of code smell, imho
Your grammar and vocabulary obfuscated your point. In other words, what?
Good tutorial for beginners. He also had some great things to say about order of operations stuff (variables, then function declarations, then invocations, then rerurns). In fact, I wish he had mentioned using "Early Returns" / "Execution Guards" at the very top of the scope before the variable declarations. To his point about when to use which style of function: don't do inline multiline declarations -- like, ever; if it is multiline then it is complex enough that it deserves to be pulled out and named as it's own operation. If not, then you're not writing Defensive Code. If you're not writing Defensive Code you are inviting corruption. That even goes for multiline if/else blocks (or loop blocks). I know we've all been taught to "always write if/else code as blocks" but you should virtually never do that. If it's more than a one-liner it has enough complexity to need be pushed into a function with a proper name, otherwise it will without a doubt become a heinous mess almost immediately. Lastly, he never mentioned writing a `new Function`. In rare cases it is the only way you can do certain things. Be very careful with that one tho because it behaves similar to `eval` which, no -- it's not "evil", but if you don't know what you're doing you can open yourself wide open to an XSS attack. Good tutorial for beginners tho 👍
This is a great episode! Super explanations by Chris! Hope Kevin and Chris will make more videos like this, especially for more advanced topics.
1:57 you would add the name there otherwise it would be an anonymous function. If an exception was thrown you would t see the variable name the function was assigned to, rather you would see anonymous function. You might want to reassign different functions to that variable in some sort of strategy pattern… if an error is thrown, it’s useful to see the name in the stack trace error to quickly find the problem.
If you have a lot of functions, consider using import and export method to split the functions into separate files. This will make your code cleaner and much easier to follow.
That bottom 'Another arrow function ' code screenshot on 00:22 actually contains a mistake: when you use an arrow function without curly braces, it means the function has implicit return. In this case adding 'return' without {} will throw an error. Correct would be: ... => num1 + num2;
That was awesome, Kevin & Chris! I've had this on my gotta watch list since it came out. It was just the right length and covered just the right stuff. And I learned more about the unique nature of 'this' in the context of arrow functions. I had known about hoisting, but Chris' explanation of it really drove it deeper into my brain. And I'm so glad you asked the question about his preference for code structure as that popped into my head right before you asked it. And I was relieved to find that I do it the way Chris does (but then, I'm old too...a lot older than Chris ;-)). Thanks again!
a guy i know work for a big tech company and they got mad at him for using arrow functions, they said let that = this was the industry standard way of writing code! he reluctantly agreed for fear of repercussions
This is great! Thanks Kevin. I really liked hearing from Chris Ferdinani. You two explain JavaScript together very well. I do not see the link to Chris Ferdinani's site so make a big button for me please.
There is a good use case for function expressions. Scope. They follow the scope definition of the variable they are assigned to. Arrow functions similarly, but personAlly I like to be explicit and make it clear a function is just that. Arrow functions are easier to misread.
i literally just now searched for Kevin Powell javascript thinking you had this type of video, I was looking for why the arrow function is important and now this gets recommended. damn
I've never used function expressions or anonymous functions.
I generally use function declarations at top-level, but arrow functions inside other functions
Great that you are expanding Kevin. On the thumbnail I believe another arrow function doesn’t require return keyword.
hoisting is done at compile time only. simple as that . function expressions are done in execution time and it can implement dynamic functionality so the reasons for choosing one over the other is more than a subjective preference but it's a question of design. Do you need run time logic? mostly not
I just started learning JavaScript and this video couldn't have been timed better. Are we going to see more JavaScript videos?
The reason is "syntactic sugar". Function declarations were provided to give a Java-y feel. Function expressions is what actually happens in JS/ECMAScript. Arrow functions were introduced as short hand syntax (brought over from CoffeeScript that has both "fat" and "skinny" arrow functions), and whose syntactic sugar is to bind "this" automatically.
Awesome! Much needed. Please create more videos on GSAP ScrollTrigger and SVG animations, Lottie animations. All combined into one series. That will be great.
In regards to his comment at about 1:50
you would name your function in the below example because that name would return in a stack trace and help you understand what function is failing instead of it being anonymous.
const example = function add(numA, numB) { return namA + numB; }
While this is historically true, engines now show the name of the variable to which the anonymous function was originally assigned. :)
For example, if you'd drop the `add` in your code, the stack trace shows "error at example".
(I just tried it out on Safari, Chrome, Firefox, Node and Bun, just to make sure)
using the function keyword can help when debugging or analyzing a codebase as you can find all functions by searching for it
Thank you Kevin! I really need more basics .js a lot of times on workshops they teach functions and stuff but not the basic logic behind. Hope to see more content cured by you!
Named function expressions will show the name in a stack trace
There's also a 4th way to write functions, though this only holds true as methods (within objects or classes). As a method, the add function can be written as `add(a,b) { return a+b; },`. If defined within a `mathematics` object, it could then be called using `mathematics.add(3,4)`
And don't forget self-executing functions: `(function(x) { return x*2; })(7)`
This is awesome. Personally struggled with the whole hoisting concept and arrow functions in javascript as a beginner. Still does to this day lol. A great part 2 vid idea would be explaining event listeners. Specifically, the difference between:
form.addEventListener('submit', submitHandler);
vs
form.addEventListener('submit', function(e){
submitHandler()
})
And
form.addEventListener('submit', (e) => {
submitHandler()
})
the difference between them is exactly what this video talks about: the different ways you create functions. addEventListener is not doing anything different in your examples, you're just specifying the callback parameter in 3 different ways.
@@rossclutterbuck1060 I probably should've said explaining callback functions within event listeners and not just event listeners themselves.
Going over subtle differences and why you'd use one over the other in a beginner-friendly way would still be useful. The second example lets you pass a parameter to submitHandler() because it's inside an anonymous function, while the first example does not.
That might seem obvious to those more experienced with javascript, but can easily trip up those starting out.
He briefly touched up on that when he said `this` would be assigned to the caller of the function.
In your first two examples, `this` will be the form that triggered the handler, while `this` would be the window object (or undefined, if the code is inside a module).
Really fun video. Seems like you've got a perfect demographic to drip feed beginner js content. I know I'm enjoying it!
Another gotcha with assigning a function to a variable is it is just a variable that you can redefine later in the script without errors
I feel var was not mentioned for confusion reasons, but var func would be accessible before declared, same way as named function.
How do you know that I’m learning JavaScript Functions now
Mind reading
He's using Copilot to record your PC screen
I just got stuck with function cause of a nav
Powell misusing AI for his own benefits
Your activity under surveillance 😜
Naming the function in a functional expression lets you see the function name th the stack trace when debugging. At least that used to be the reason to name them. I haven't used that pattern in a long time.
Within objects and classes there are _3 additional syntaxes_ for creating function properties.
{
foo() {},
get bar() {},
set bar(val) {}
}
those last 2 are setters and getters, they are functions, but you cannot declare any function with them
Like minds :)
One of my biggest complaints about ES6 was all the new syntax for objects, classes, and functions that wasn't required. It was just sugar. There was also sugar for promises that I was happy to have...
It's worth mentioning the use bind to bind this to the containing context's this.
Good to see JS tutorials in your channel mr Kevin! thanks! 😊
Brilliant Chris, and thnx Kevin for sharing him with us.
Great video! Very concise and informative
8:47 I'm interested in the advance version of this video 😸
What a great explenation. Thx
naming of anonymous functions is helping when generating jsDocs or just when debugging those (names in stack traces and breakpoint availabilities).
Awesome explanation, thank you.
Great information, thanks for sharing!
Great video again, Kevin! Nota dez! 🤘🏻
Where can I get more of the guest teacher? he is great!
First link in the description :)
Excellent explaination of the various kinds of function in Javascript. Thanks Kevin and Chris.
{2024-06-13}
very very explanatory thank you
Thanks Powell :)
1:40 - The name is sometimes added because debugging JavaScript code in browser is an absolute disaster, in my opinion.
Imagine you have a mutation observer that automatically sets some event handlers.
Imagine the event handler threw an exception, because of some reason.
Instead of looking into an inside an , you look into the function and then the .
Oh, and when the code is wrapped in an onload event, that adds even more to the confusion.
i tend to nest utility arrow function expressions in function declarations for scoping & readability.
What happens when you assign a function declaration to var instead of let?
Another good reason to use function variables is you can pass a function into a function. e.g. callbacks.
Thank you kevin
There's an implied return in bracketless arrow functions. Removing the brackets from the arrow function changes it from void to returning a number. Doesn't make a difference here, though.
What is the downside of using .bind(this) on the function, instead of using a lambda expression or referencing 'this' somewhere else @11:55 ?
.bind creates a new function that wraps the first. This is technically less efficient with memory and call time, but practically makes little difference.
The really cool thing about function expressions is that they can be reassigned during runtime. Imagine that you want to assign a function based on their handling of a particular language where the language is not static during runtime, such as processing data that contain strings written in one or more languages for example.
you can actually reassign any function that is not explicitly a function expression stored in a const variable independent of if its a regular function declaration or function expression!
Yet another edge case: when you have a function written with FE approach through var and it’s called before initialization, we get a different error as opposed to using let keyword.
Does Monokai have a light version?
Function expressions in other languages will assign the return to the variable and not the function itself, I am certain that this isn’t known as an expression in JavaScript and that it is just an anonymous function. But this is JavaScript and they name expressions wrong, just look at a language like Rust and you will see that expressions always assign values based on evaluation and not assign the reference to the function, this would be a statement as the value isn’t returned. Using an immediately invoked function would assign the value and not the reference.
Once you learn more languages you wouldn’t use the term of expression to describe what is actually being defined with that code, just a heads up for learning other languages.
Just to prove a point, try this let x = function y(z) { return z; } and see what happens, you will be able to call x(“test”) which will return z. So, is this an expression or a declaration? This is the very reason I find this use of the word expression misleading. You will now find that y is undefined and that x is a function named y! Just try this in the console and you’ll find that when x is evaluated it will show a function called y that you can’t call.
Bald Adam Lambert seems to know his stuff
When is the vid on prototyping?
nicee more js videos would be awesome
dark mode would be nice
What’s up with using let everywhere? Is he going to be reassigning all of the functions he was assigning to variables? This would be so confusing, whenever I see I let I start searching for the reassignment.
exacly, people should use const more, and use let only for variables that actually change value
and don't get me started on the ones that use var for everything 😂
Also, let and var should be used based on whether it is needed only inside or also outside the block where it is declared. Avoid making everything global, keep it inside where it is needed to be used. Especially utility variables inside a function, loop counters, temporary vars, placeholders, etc.
Great 👍
Another 'benefit' of function expressions is that you can dynamically re-assign a different function to the variable at any time. So you could dynamically change what 'add()' actually does. Sounds bloody dangerous to me, but anyway.....
unless you're using TS, you can override a function at any time.
this is all valid:
function f() {/* do something */}
function f() {/* do another thing */}
f = function () {/* do yet another thing */}
The first two will be hoisted because they are function declarations; the third one will be evaluated in order because it's an expression.
@@feldinho But you cannot decide at run time which of the first two will be called
Arrow functions. should be called "lambda function" or "lambda expression" as that is there technical name.
I have eyes problems and that white screen just hurt my eyes hahaha, otherwise great and useful content :)
long waited video ...
13:34 I've never understood how verbose code is "easier" to read. It's more to read. How is that easier?
It’s not exactly personal preference. You definitely don’t want to use expressions to declare “methods” (doing it this way makes it not a method) on a class. If you don’t use regular function declaration syntax it won’t be on the prototype and every instance will have to recreate it.
let that = this, if i was in that era i would hate programming 😂
thumbnail has `return` in one-line arrow function, should be ommitted
Shouldn't all those lets be consts? It almost never necessary (and almost always bad practice) to update variables that contain a function. My linter would go insane 😅
Light theme is killing me
Dark mode or no learning!
I love your videos Kevin but that thumbnail triggered me because it's wrong. The last example...
let add = (num1, num2) => return num1 + num2;
...will trigger a syntax error. You need to remove that return or put them inside curly braces. It's either one or the other, not both. Either the ones below:
let add = (num1, num2) => num1 + num2;
let add = (num1, num2) => { return num1 + num2 };
If it was made on purpose to receive engagement, there, you got me. I hope not though.
Also, the one labelled 'function expression' is an arrow function.
Went a bit too fast putting the thumbnail together, thanks for mentioning it! I'm off the computer atm, but will fix it tomorrow 👍
@@KevinPowell oh I completely understand. Thanks for the videos as always 🩷
Quantum entanglement
const
Some days it's just hard to function.
"code golf"
Is there a tool to invert the colors of yt videos? I work at night and I'm actually wearing sunglasses.
blinding alert!!
You didn't even mention object and class methods. All JavaScript functions declared with the keyword (whether declarations or expressions) are created with a function.prototype property that's an object holding a reference back to the function as "constructor" and any other functions that will become class methods, whether they're ever actually used as classes or not. They can also be invoked with the "new" keyword, which can make zero difference or every difference depending on what the code does.
Both arrows and class/object methods don't do that. They don't have the overhead of a prototype property and can't be invoked with "new." This is good practice to provide interfaces that can be used in exactly one way, to prevent footguns.
Arrow functions have neither an inherent "this" property as you discussed, but also don't have an "arguments" construct. Any attempt to reference "this" or "arguments" from inside the function will use the lexical scope instead of passed scope. I have a typehinting library that uses "arguments," but otherwise this is useless overhead you can chuck with an arrow function. Rest parameters removed the primary use case for the "arguments" construct, for variable argument lengths. Class/object methods still have both, allowing call/bind of a specified "this" and arguments introspection.
Hoisted functions are also treated as if they were declared with "var." This means A) they use function scope, not block scope and B) they can be _redeclared_. For that reason alone, it's useful to use arrows or function declarations with a "const" keyword; there's nothing like a nasty surprise of having a function get redeclared into a variable because you reused a name. var will happily allow you to redeclare a variable over and over again within the same scope; let and const will halt on redeclaration, and const will halt on any reassignment.
I absolutely don't like arrow functions and rarely ever use them.
JS devs be like: console.log(this);
You used arrow functions twice in the thumbnail
Please don’t use ‘let’ or ‘var’ to declare functions. Use ‘const’ instead. Const will prevent you from accidentally overriding the function declaration. let count = () => {}; and then you can do count = 5, which will break if you do count() later on.
let… var… :0
My 3-cents: Terse code is harder to debug, harder to read, and harder to set breakpoints (debug). Also, arrow functions with implicit return statements and lean coding constructs may be convenient once you figure out all of these tricks, but they are a real pain to learn. That is to say, you don't really know what the code is doing sometimes if you don't know the "hidden" rules behind the syntax. Old school code is more explicit. It doesn't hide anything and you can figure out what it's doing just by looking at the code. You don't have to look up some "hidden rules", etc. to figure it out like you do with the newer JS syntax. Personally, I prefer verbose code and "old school" syntax (traditional constructs) because it's easier to read, debug, etc. For my coding adventures, I want to be able to set a breakpoint anywhere in the code without having to rewrite it. That makes it more maintainable, which the newer kids on the block seem to devalue or ignore altogether.
I just dropped in to say your thumbnail is wrong. a function expression would look like
const example = function add(numA, numB) { return namA + numB; }
Hum, no ?
I'm so disappointed! Normally Kevin knows every insane poorly documented way of doing things but the new guy never mentions half of the types of function.
Generator functions, syntax: function* foo(){}
Async functions, syntax: async function(){}
and last but not least the Function constructor! syntax: new Function()
the explaination of "this" was nice but if you go there we also want "arguments" and perhaps the scope?
Come to think of it, now that everyone insists that what was always called "arguments" should now be called "parameters" why are they called arguments if they are parameters!?
Feels wrong , just a JS video. I mean not even a little CSS ? Sorry dude but there is literally 1000s of other videos explaining on how functions work. 😢
You messed up function expressions in the thumbnail. Should be 👇🏾
let foo = function () {...}
Also => without {} has implicit return so it's not valid to write => return
let instance = this;
was the most used way. Function.prototype.call and Function.prototype.apply where introduced later into Javascript to allow calling a function while also passing (overriding) this. E.g.
function sayHello () {
return `Hello, ${this.name}`;
}
sayHello.call({ name: 'Chad' }); // This will return "Hello, Chad"
And later still Function.prototype.bind was added that lets one do e.g. this:
let sayHelloChad = sayHello.bind({ name: 'Chad' });
sayHelloChad(); // This will return "Hello, Chad"