Making Sense of the Tricky Parts of JavaScript

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
javascript can be confusing right that this keyword prototypes callback functions scope and hoisting and a couple of other things especially if you're new to JavaScript but even as a bit of a more experienced developer these things can be tricky now in this video as well as in an article below the video and a course which can optionally take I compiled these different strange aspects to hopefully make them a bit less strange scope and hoisting are key concepts of JavaScript and this snippet shows us both in action now what's scope the scope is all about the visibility of variables so where in your code you can use which variable for example that we can access the result variable here inside of this function but also here outside of the function is possible because we declare and define it here in line 1 and therefore this function uses the so-called global scope actually since it's created with let it technically uses block scope but this all sets in one big block of code and in JavaScript scopes work such that the variables defined in a scope can be used anywhere in that scope but also in any child in any nested scope now it turns out functions create their own scope if you create variables in there with the VAR keyword those variables have function scope or if you create variables with let or a constant there those variables or constants have block scope because functions just like if statements and for loops create new blocks of code so a variable defined in a higher-level scope can be used in a nested scope so global scope can be used inside of this function or block scope it would not work the other way around if I have a new result here where I use basically the other result I could not use new result anywhere here no matter where I try to use it this would not work because this is now a constant created in this block of code and therefore it's only available in there or in any other nested scope that's what scope is about in the end and knowing it it's very important because it explains why you can access certain variables in some parts of your code and why you can't in a verse now another important concept in JavaScript which also can be tricky to wrap your head around is the concept of hoisting hoisting is in the end just a core mechanism built into JavaScript or into JavaScript engines that run your code dead in the end and ables javascript to be aware of certain variables and functions before the code execution reaches the function or variable declaration okay that's a very technical turn what does it mean well we see it here we're calling add one in line three but keep in mind that we actually only declare and define this function here in lines six to nine now because of the hoisting mechanism JavaScript essentially goes over your entire file before it starts executing it and you could say it memorizes all those function declarations so functions written like this and that's why you're then able to call such a function when the code execution begins before the code execution reached those lines down they're important for hoisting is that it really only works in that way if you have a function declaration so if you use this function declaration syntax if instead we would have created a add one constant and stored an anonymous function in there and hence we would have used this function expression syntax the add one variable would kind of be hoisted but you wouldn't be able to call it so hoisting is really most important to be aware of or to utilize if you're using this syntax because this then allows you to move functions to the end of your file which can help you organize your code primitive values and reference values that's a topic that's definitely confusing to a lot of developers numbers in JavaScript as well as strings bullying's undefined symbol and big int for big integer are so-called primitive values any object in JavaScript is a reference value and for that it's important to keep in mind that arrays and functions are also objects in JavaScript now that's a nice differentiation but what's the idea behind it what does it mean primitive values so numbers strings boolean's and so on are immutable and shared by copy reference values are mutable and shared by well reference but again what does this mean here's an example we have a number one analog number plus two and then I also change number here and store a new number in the number variable now this is straightforward code but it is important to realize and understand as developer that behind the scenes the value 1 here is actually never changed when we add 2 to it we're not changing the 1 the one always stays a 1 we of course do something else we derive a brand new value of 3 here and we output this year so neither the value stored in the variable has changed nor the value itself behind the scenes in memory it's always a 1 we just derive a new value here and this is achieved by copying it by value so what this means is that when we have a calculation where we use a value that 1 is simply copied here and we derive a brand-new value the same here and when we then store it is back in number we're not changing the old value the 1 still is a 1 we just don't need that one anymore we copied it here so that we can derive a brand new value the 4 but then the original 1 is simply dumped we don't need it anymore we got a brand new value of 4 and that 4 is stored here in number now that's just some theory which is nice to know but which doesn't really change how you your code you probably didn't expect anything else than what I explained here from this code anyways right well it gets more interesting when we talk about reference values because that's the tricky part as I said any object in JavaScript is a reference value and that includes arrays and functions now here we have a straightforward simple object an object with an age property which has a value of 31 now the 31 of course is a primitive value it's a number but the overall object is a reference value now I create a new constant me and I saved as object which is stored in person in me because I point at person here and then I changed the person age set it to 32 analog me age so I changed the age of person not of me but then I log me age and if you would lock this you would see that indeed you get 32 as output not 31 even though we never changed me dot age and the reason for that is that reference values in JavaScript are stored such that we have one object stored in memory and what's stored in the constant here or in the variable doesn't matter is a pointer at this object in memory so the address of that object in memory you could say the reference to it that's stored in a constant and when we create a new constant here we just copied that pointer and store it in a new constant as well but if we then use that pointer to manipulate the value we work on one and the same value in memory because that value in memory was never copied or cloned or anything like that it's one of the same object with one pointer and just that pointer was copied and that's why we manipulate the object stored in me when we assign a new age to the person object because it's not two different objects it's one object in memory and that's also why we can manipulate a Const this is a con so we can't change the value stored in there right why can we then assign a new age well because we're not assigning a new value to person with that we're changing the value the pointer point set but what's stored in this con is not that object but the pointer and the pointer doesn't change we wouldn't be allowed to assign a new value to person let's say a new object this would throw an error because here we really would create a new object a new pointer and try to store it in person but what we do here is perfectly fine because we're just changing an existing object in memory now there are techniques how you can copy an object so how you can not just copy the pointer but the full object and I do dive into that in the resources below the video but for now that's what you need to know about primitives and reference values closures can be the cause of a lot of trouble if you don't know how they behave and what they are now in general every function in JavaScript is or to be precise for ins a closure now that doesn't help you too much right now what's a closure a function JavaScript as we have it here simply closes over its environment when it's created and that means one simple thing it memorizes the variables it has access to when the code that creates it executes it and the consequence simply is that if a function is called at a later point of time like this anonymous function here which we call only after one and a half second it still has access to this my name variable here even though it's running in the future so when the average code execution already finished it still has access to my name because the environment of this function when it was created contained to my name variable because of that scope concept we have access to the global my name variable here in this anonymous function but closures can still be tricky we have access to my name so what would you expect as an output here if I load this page keep in mind that this runs after one and a half second do you expect max here which is the value we have when we call that function that sets the timer or do you expect Maximilian which I change after calling this function that sets the timer well it's Maximilian and this might or might not be what you expected now I think it would be reasonable if you expected max as an output instead of Maximilian after all when we set the timer when we called greet me with delay the value was max so if the function this anonymous function in this case closes over its environment and in this environment my name is Max at the point of time we create this function why do we then output Maximilian when the function actually runs because and that's important functions closures in JavaScript closed over the variable names you could say they memorize the variable names not the variable values the value is only look up when the function actually runs so the value for my name is only looked up when this anonymous function is executed which happens when a timer completed and at that point of time the value is Maximilian because we immediately changed his after setting the timer and that's the essence of closures in the end recursion is a concept that's not exclusive to JavaScript actually a lot of concepts covered here are not necessarily exclusive to JavaScript but recursion can simply be tricky because it's it can be difficult to wrap your head around it and here's a simple example for it recursion is basically just a function calling itself like we're doing it here we're calling factorial from inside factorial and yes this is something you're allowed to do in JavaScript now why might you want to do it simply because recursion sometimes allows you to write less code then you would have to write with a loop or in some cases like if you're traversing some tree structure recursion might even be your only strategy of handling a certain situation like in such a tree structure traversal situation where you don't know in advance how many iterations you might need because you have a nested object and you need to go through all levels of nesting something like that I cover that in my course but even in this simple case this can be shorter than the loop you would have to write otherwise now a good recursive function in the end always has at least two components a base case which is basically your non recursive exit condition where you return a value where you don't call yourself and recursive step which is essentially you calling yourself if you only have recursive steps so if you have no branch in the function where you don't call yourself you of course create an infinite loop and you don't want that and therefore you need some condition in every recursive function in the end that cancels the recursion and gets you out of it now if I lock this here we therefore a see the result six and if you want to look behind the scenes of recursion you can do this as well with the developer tools for example by simply adding a breakpoint here in your recursive function if I now reload it stops here and what you see here in the developer tools is to call stack the call stack is a mechanism that's part of the JavaScript engine in the end which managers running function executions javascript is only capable of executing one function at a time but it can you could say pause of function execution to wait for another function to finish and you can see this here if I continue here and I step into the next function execution you now see on the call stack we have Q factorial function executions going on and the one with the blue arrow is the one we're currently in and that's recursion in action we got more and more ongoing factorial function executions but only the top one is the one that's currently executing and at some point once we made it deep enough into all of that we make it out of the recursion and go through that call stack from top to bottom to basically return the value of every nested function execution to the next one in line in the call stack until we're back to the main function execution which then ultimately is able to complete and return us the value were interested in that's how recursion works under the hood and that's how you can debug it and how you can hopefully avoid a lot of headaches related to that callbacks and related to that direct versus indirect function execution can also be confusing to newcomers here is a classic scenario of regular direct function execution we have a function we then call it and you call a function when you basically add parentheses after the function name after having the function to find of course this then executes this function right away and runs whichever code is in it now here's an example for indirect function execution where we utilize a callback we add a listener to a button here and this add event listener method does not only take the kind of event you want to listen to but also the function that should be executed when the click occurs and I often get asked why we don't have parentheses here the reason is simple if we would have parentheses here after add user in line 9 we would immediately execute add user when Javas good reaches this line of code now it reaches this line of code not when a click occurs though but when it simply adds to click listener and that's of course not when you want to call this function this should fire when the click occurs instead so adding parentheses here is definitely wrong because that would always lead this function to be called when the listener is added not when they click occurs if you remove the parentheses you pass something else to add event listener you pass the name of the function that should be executed eventually to that add event listener method you pass a pointer at this function object to add event listener and add event listener internally then we'll use this argument and the value stored in it so the function and call it for you when the time is right so in this case when I click OK and that's what I would like to call indirect function execution but this of course awls is a concept which is simply called callbacks we're using a callback function here we're passing a function as an argument to another function so that that our function can eventually call us back and call this function for us when the time is right and that's why we don't add parentheses here and how callback function work in the end now as with all the concepts below the video you of course find a more detailed resource on that this is just a brief summary of course because when it comes to for example pre configuring parameters add user should receive eventually you need to use certain tools like the bind method which is in JavaScript but again that's covered in the additional resources now we just saw callbacks in action one area where callbacks are typically used is the area of a synchronous code now javascript is single threaded which means it can only do one thing after another and setting a timer and then executing another part another piece of code works but maybe not in the way you would expect it to work because JavaScript when you set a timer does not pause code execution it only has one thread available to perform tasks to do work and it does not pause when you are setting a timer or sending a HTTP request because that would mean that your scripts are basically worthless if they can only do one thing at a time modern web applications where a lot of things happen simultaneously would just not be possible instead javascript offloads certain tasks to the environment it runs in like the browser with set timeout which is a function made available by the browser in the end it simply offloads the task of setting a timer to the browser and the browser also you could say memorizes the function the greet function here on the slide that should eventually be called when the timer completed so the browser manages the timer and JavaScript can continue do other things it can run our code synchronous code so code which finishes instantly and when the timer expired when the time is up the browser will notify JavaScript about this and tell it hey you gave me that greet function please execute it now and JavaScript will schedule this greet function to be executed as soon as possible so as soon as it has no other work left to do on its single thread that's how a synchronous code so code it takes a bit longer you could say works in JavaScript JavaScript performs task after task so setting a timer and console logging and this all happens basically instantly after another it does not wait for five seconds here instead it directly moves on to the next line and only executes say hello after five seconds because the timer is set and managed by the browser and it basically tells JavaScript when the time is up that's how asynchronous code works now callbacks are always important in asynchronous code but for more complex asynchronous code structures or snippets we also have the amazing feature of promises in modern JavaScript here's an example the fetch API is an API built into the browser and it sends a network request and get some data now when we get that response we often want to parse the data that's in the response and it turns out that in JavaScript as this API is set up this is another a synchronous task so this JSON method which basically parses the response data and gives us a JavaScript object does not finish instantly now if that fetch API which is built into the browser would use callbacks only and not this promise concept this might look something like this we have fetched we have a function that's executed when that fetch process has finished when we got a response in there we call Jason and to Jason we pass another function which is executed once the data has been parsed and if we do more and more asynchronous work we have a deeper and deeper nesting that's called callback hell because it can quickly get quite hard to read now promises work differently a promise is simply a JavaScript object that has a ven and a catch method and fetch return such a promise we can basically call the then method to set up a function that should be triggered that should be executed when the promise resolves so when it's done with its work now the trick is that every then method then by default returns a new promise or if we return a separate promise as we do here jason also yields a promise that default promise is replaced by that return promise so long story short then always yields a promise object itself which is why we can chain then calls we can call then after then because then yields a new promise and this allows us to set up steps of code that executes after each other first we wait for the response we start the data parsing process and that finished this code here this function here execute and error handling is also easy we can add a catch method in this chain here because every promise does not just have then but also catch and catch will trigger this function when any prior promise fails so this promise or this promise or the main fetch promise if any of those free promises fails this function here will execute that's how promises work and of course there's a bit more to them in my JavaScript the complete guide course as well as in the JavaScript the tricky parts course I dive a bit deeper into them here the key take away is how asynchronous code generally works that tasks are offloaded to the browser and that we have callbacks and basically the enhanced version of callbacks promises to then orchestrate our code steps our code snippets that should be executed when such tasks finish okay you probably waited for it one of the most tricky things in JavaScript is that this keyword it can really behave strangely and here's an example when I call output info I in the end call this print age method because I stored a print H method in output info in line eight so we would expect to lock the age of the person here right because that's what I'm referring to in line 4 which is in that method that's being called however if I reload this in the browser we see undefined instead of the age and Dad simply happens because of the way that this keyword works this unlike in other programming languages does not always refer to the object it's it's written in you could say instead this and that's a good rule of thumb refers to who called a function if you're using this it only matters about the functions being used in and who called that function and if we for example do person print age you will see that we get this age output here and the reason for that is that we call print age on person so person called dead function you could say and therefore this inside of print age refers to that when we call output info like this you could say no one called that function or that function is called on nothing and therefore this inside of the function refers to not nothing but actually to the global window object that is you could say it's it's fallback if it's not called on anything else and that really is the most important thing to memorize about this when you think about what this refers to you should look at the function that's being called and how it's being called and if it's called on something this will refer to that something if it's called like this this will not refer to the object it might be Whiston but simply to something else typically to the global window object so looking at who called something and how it's called is the key to understanding this now there still are some special cases like having an anonymous function in an eventlistener where this will not refer to the window object but to the elements that caused the event but that's covered in the additional resources below the video if you want to dive into that the key takeaway is that rule of thumb that you look at who called a function or on what a function is called and dead this then refers to that what now the last tricky thing I wanna dive in in this video are prototypes prototypes are an essential part of JavaScript they are the key concept when it comes to inheritance in JavaScript and yet prototypes can be hard to understand and to reason about and the name is part of that prototype sounds like blueprint at least to me but a prototype in JavaScript is actually more of a fallback object and that's the core idea of prototypes every object in JavaScript has a prototype and you either get a default prototype if you create an object like this then the default prototype is object dot prototype more on that in a second or you create an object for example like this with the create method on the object constructor function and you can set the prototype of the to be created object to some other object in this case user has person as a prototype and the consequence is that if we access a property on user which doesn't exist directly on user javascript has a look at its prototype and the prototype of user which is person does have that kind property and that's really the essence of prototypes prototypes are fallback objects in JavaScript you can set them when you create an object like this you can change them after an object has been created with set prototype off for example and you can also set them on constructor functions here we have the person constructor function and there we have that special prototype property which is often misunderstood using that prototype property which exists on every function object in JavaScript does not set the prototype of this person constructor function object instead we set the prototype of to be created objects that are created based on this constructor function so by executing the constructor function with the new keyword so max here has human as a prototype as a fallback object because the constructor function is pre-configured to give it that prototype that's what the prototype property does if you want to find out which prototype an object has you can use the underscore underscore proto underscore underscore property this is a non-standard property which means it's not part of the JavaScript standard but most browsers support it and this gives you the prototype of an object it's nice for analyzing your code it's nice during development but otherwise not a property you should really use instead this year this prototype property allows you to pre-configure prototypes on constructor functions and you got the aberrant methods you saw before for setting and changing prototypes in addition in modern JavaScript you also got the class keyword and the extends keyword to extend another class so to have inheritance and under the hood this also uses prototypes but I dive deeper into that in my tricky parts course the essence of prototypes is that their fallback objects Java Script uses to look up missing functionalities and if you wonder why we have that let's have a look at an array one two three a simple array of numbers now that's a straightforward array and if I log it it's not too exciting what we see here but we actually see something interesting if we take a closer look this array object arrays are objects after all has free keys 0 1 2 & 1 extra keep the length key okay that's all nice that's what is created when you create an array what you don't see in this object however are all those array methods like push or map or filter and you of course know that those methods exist on arrays now they're not part of every array object because dad would take up a lot of space in memory if you work with a lot of arrays in your code and every array has all those methods no matter if you use them on this array or not that's a lot of extra stuff to store and to manage and that's not great for memory and for performance therefore instead a newly created array has a special prototype a special fall bag object which then has all those methods so which has push and pop and all those array methods and every array has that same prototype object so that utility object with all those methods is only created once it's only stored in memory once and then every array is just linked to it through that prototype concept and that's why we have prototypes it makes managing code easier and allows us to for example optimize memory and performance
Info
Channel: Academind
Views: 33,633
Rating: 4.9602556 out of 5
Keywords: javascript, js, scope, hoisting, javascript scope, javascript hoisting, prototypes, js prototypes, js scope, js hoisting, closures, recursion, loops, js closures, async, js async, js async await, js promises, js promise, academind, maximilian schwarzmüller, maximilian schwarzmuller, maximilian schwarzmueller, callbacks, js callbacks, javascript the weird parts, full course, tutorial, js tutorial, js course, javascript course, javascript tutorial
Id: tiRhFGnCltw
Channel Id: undefined
Length: 31min 11sec (1871 seconds)
Published: Thu Apr 02 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.