What the lexical is this?

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey today we're going to be talking about lexical scope and this now this is the javascript keyword this and the point of the video is really to try and help you understand how this works i want to help you avoid errors and pitfalls that are based on understandable but erroneous assumptions about what this means so we're going to go through this list down here at the bottom i have some code here at the very end of this we're going to get into event listeners in the browser and talk about how this works with those but we're going to go through the list here we're going to talk about the new keyword how that impacts this what explicit binding is what implicit binding is how you strict impacts this what default binding is and then how arrow functions use lexical scope and how they're attached to the keyword this or how they force the keyword this to be interpreted and then finally we'll get into event listeners now this list that you see here at least the first six items here this is sort of the list that the browser goes through when it sees the keyword this it's sort of running through this list to figure out how it is supposed to interpret this so we're going to talk about each of these and hopefully by the end of this you'll be an expert in understanding this you'll be able to explain it to other people and then really understand it better yourself all right so we're going to ignore this bit of code we'll talk about this at the very end the stuff down at the bottom here new let's talk about the new keyword first of all so i'm going to create a function here i'm just going to call it f now i can write it this way with the variable declaration or we could write it as this like that either way it's going to do the same thing so whether it's the function declaration or the function expression it works the same way as it pertains to this so inside of here i'm going to write out what this is now if i call this function so save that we'll run this in the browser and here it is that's what this is it's the window object in the browser if you're running this through node.js you're going to get the global object there is an object actually called global which is the global object in the browser you're going to get window as the result of this that is because inside of here we're actually jumping down through all these things we're getting down to the default binding and we're looking here at the keyword this the browser looks at this or the javascript interpreter looks at this and says okay what is the context for running this function right here and that is the window object you can see right here we're in the global scope calling this function so the window object is the global scope effectively and that's what this is going to be now if i get me to erase that if i say new f like that i'm using the new keyword to turn this function into a constructor function when we do that we are turning this into the object that is being constructed by this function that's why it's called a constructor it's constructing an object and there it is it's an object of type f there's my whole function so we have an object being created that is going to be returned now i haven't put the return keyword in here if i was to do something like that so let's just call it f obj there we go we can see the thing that was returned from the function that is the object of type f so this thing is a constructor it built an object and if you use this inside of the function and you call it with the new keyword you're turning that function to constructor and it will return this this is the new object that's being returned all right great so that is the first one down pretty simple if you see new this is going to be the object returned by that function okay next one explicit binding with call apply or bind now all three of these functions call apply and bind are doing the same sort of thing call and apply the only difference between the two of them is with call my first argument for doing that is going to be the context and then everything else is going to be a list of arguments i'm passing to the function with apply you pass in the context and then you pass an array so there's only two arguments so call we get the context followed by argument argument argument argument argument just like that with apply you pass in the context and then we pass in an array of things like this so that's the difference between call and apply bind works the same way as call except it returns a copy of the function so bind same as call all right so those are definitions of what we're doing how do they work and what does it have to do with this we have our function here f okay i'm going to create well i'm going to use that function i'm going to say f i'm going to call it and now i am explicitly going to tell it what is the context for that function to run here f the context was the global scope the window object so if i put window here i'm passing in the window object as the context for calling this thing if i pass in no i'm saying there is no context for calling that if i call this with no basically i'm saying i'm not giving you context we're kind of jumping ahead to the use script and what's going to happen there this is going to write out the window object again in the browser we'll come back to that one though or if i have some object so let's say here that i'm going to create an object i'll create an object x x for explicit and i will give it one property a one actually let's make a copy of this function here as well so we don't we can make changes to it let's call this f x for function explicit so here's my first object object x i'll make another one so we can play with both of these and obj x there we go that is the context now so what i'm doing is i'm calling this function right here and inside of here i'm saying i want to use this thing as the context this points to the context so this will be this object x there it is there's object x if i change this to objects 2 that's this one there it is we've jumped to the second one so we can specify anything that we want as the context for doing this if i say window window is the context if i use the document object the document object is the context for calling that function so whatever i pass in here that will become this inside of that function as long as it's not an arrow function and we'll come back to those everything else that we passed like i said here in the definition if i passed in the numbers one and two up here there we go there's a and b that will be the one and that'll be the two and this dot a if i go back to one of those two objects here objects so my a b that's going to be the 1 2 this dot a well if objects is my context what is the value of a inside of objects well it's this a1 so i should get a1 back there we go there's the one two and there's the a1 all right so that's explicit binding so we've got the constructor function we've got explicit binding and just as a quick demonstration for bind i can say let f2 equal there we go what i'm doing here with oh sorry not called bind this is the example with bind i'm going to run the function fe x so this function is going to run i'm passing in this as the context right here this object now i don't have to pass these in right here i can pass them in later what i'm going to get back from this is a copy of this function where obj2 is the context so obj x2 this is now a copy of that function if i run it like this and then we pass in the 4 and 5. there we go we have a copy of the function fex but in this copy it is understood that obj x2 will be the context for this there it is there's the four five and the a2 so this is the second time running if we comment out this one there it is so four five that's what we passed in here and obj ex2 gives us that second object so there's the property a inside of there okay so that's explicit binding now implicit binding this is the one that gets a little bit more confusing for some people so with implicit binding what we're doing is we're telling the function okay i need you to look and see what the context was for calling you i haven't told you outright you're going to have to look and check so we will say i'm going to comment this one out we're going to create a new one here for the implicit all right so i've created an object here property a and a property f um the f property is a function now this is sort of the the new shorthand syntax for writing methods inside of objects we can also do this we can say that f is a function these two syntaxes are the exact same thing here i'll throw another one in there just so you've got the two of them you can look at them side by side there we go so f and g exact same thing regular functions they handle this the exact same way i'm not using arrow functions here because arrow functions will change the context and we'll come back and talk about that but here's our object and now what i want to do is i want to start calling these functions if i was to say obj dot f what i'm doing here is i'm calling this function f this one so i'm calling that function and the context for calling this this points to the context the context is going to be here this obj this is the thing this is the context this object so my function what is the value of this right here well it's this obj object so that first one obj this one right here what i'm doing is i'm creating a new reference this f3 is pointing to this so we go to the obj object we find the thing called f what is it it's this function right here so f3 is now a pointer that goes directly to this if i call f3 i'm talking about the global context here f3 is not inside obj f3 is just a thing on its own it's just a direct reference to that function so we're going to get that window object there it is so here's the first one here's our obj which is the whole thing this whole thing right here this is obj so when we said obj.f we're calling the function and we're providing a context right here the thing that's in front of the method name for the second one because i pointed directly to this what i've done is i've kind of skipped over the fact that this is an object i've just pointed directly to this thing right here well if i just run this on its own like i have here its context is now this global context it's the window object okay so i'll give you uh an example here of where you could go wrong if you're not quite sure of what the context is going to be so let's create a function here i'm going to create a function that's going to be like a counter i'll say this dot count and we'll increment it so every time we call it i want to increment a property called count on this now this depends on the context you look at this code and logically you might think that this is talking about the function because that's where you wrote it and that's where the lexical scope comes into play lexical scope lexing is a process that happens when javascript runs it's actually passed through the interpreter a couple of times the first time is the lexing or the tokenization where it reads through your code and it figures out where are all the variables where are all the references to the different elements and what is the scope right here as it's written that is called lexical scope so where you've written something right here so this property a its scope is inside of the object obj okay that's lexical scope this uses a different scope it doesn't use lexical scope in regular functions you have to put this inside of a function you can't just write this on the the main timeline when i write this the lexical scope says okay where is this function what is its scope that's what my this is going to be my context for this arrow functions are going to use the lexical scope and we'll come back and talk about that but everything else beyond this uses lexical scope so a is inside of obj the context for a is obj functions when you're using this you're talking about runtime not read time so not when it's being tokenized not when it's being lexed the lexical scope doesn't apply to this inside of regular functions or even the es5 shorthand version of the functions so here in this function where i'm adding one it looks like it because everything else in javascript you're talking about lexical scope so it looks like you're writing a property on this object right here this function object so you can say to yourself well okay what if i give a starting value of count as zero thinking oh yeah okay i've got a property count it's on the function add one i'm setting it to zero and that is exactly what this line does here's the context here's a brand new property functions in javascript are just objects so i've got an object called add1 i've just created a property called count on that object and i've set it to zero here it all depends on the context when it runs so if i just call add one and i do this a few times like that you might read through this and think oh okay yeah so the value of add1.count at this point is going to be three but if we log it out so say that i'll comment out these other ones there we go so i want to see what the value of add1 count is zero it says it is zero because i set it to zero right here however what i was actually doing inside of here was what's the context for running ad one on these three lines right here the context is the window object it's that global object so on the window object i've got a property called count and i'm trying to increment that because there is no starting value in this every time i try to increment it it's taking undefined and it is trying to increment undefined so i'm going to get not a number as the result here so this one's coming back as 0. if i say window dot count look at the number for that i'm going to get not a number there it is had i here said window.count equals i'll just throw in 8 just to have a different number now we can see 11. so it was being incremented this although at a glance looks like you're talking about the function this doesn't do that this uses runtime to determine the scope okay now i'm going to do another example here just because implicit binding is some of the most challenging to wrap your head around i'm just going to copy in a bit of sample code here and just talk about the results so i've got another function where i'm going to write out the value of a i've got an object one where a is one object two where a is two object three where a is three so i've got the three different values f4 inside of obj1 is a direct reference here to that function in obj2 what i'm doing is i'm pointing to this first object so this object inside of it has a property called f4 and number three i'm pointing directly to it so this is a lot like the example that i did up here where we're talking about the direct reference versus the one with this context so the window context or the object context obj1.f4 okay obj1 f4 i've provided a context here obj1 is the context for this so when i write out this dot a i get the value 1 from inside of obj1 so that is the context so that's the value obj2.obs1.f4 obj2 it's at the start of the chain looks kind of like it might be the context for the whole thing but really we've gone from obj2 down to its obj1 property and then this right here this is the context for calling f4 so we're calling this f4 obj1.f4 well it's the obj1.f4 which is a reference to that function that's the one that we're calling so we get the same binding here obj1 right next to it that is the thing that provides the context just like here obj1.4 obj1.f4 the thing that's right inside right in front of the function that is the thing that's giving the context obj3.f4 because inside of obj3 we made its f4 property a direct reference right here obj1.f4 so we're pointing to this thing right here which is a direct reference to f4 we've made this the thing that is in front so this becomes the value so the first two we get one where both you they're both using ob one as the context and for this one obj is the context all right so i hope that makes sense for the implicit binding now the couple of other things that will impact this one is use script if we add use strict whether it's on the entire file so up here at the very top i say use strict i put my page into strict mode my script into script mode strict mode or we can put ustrict inside of the function itself if we do that we're losing this default binding this thing that i've been talking about all along about how it points to the window object that is the default binding the window object or the global object if we don't provide a context like here in this very first one when i just call that f that first one we're saying okay yeah that was the window object but now with u-strict we're saying don't use default binding that's that window global binding it doesn't exist now so we're actually going to get undefined instead of javascript saying okay yeah i'll just use the window object you haven't really explained what the context is so i'm going to use the global object so i'm going to comment out my ones down below here that i was running just don't want all the other console log statements to come up there we go back up to the top so when i call f now undefined i'll go down here and turn off or stop these running because that's what's causing the other error there we go undefined that's the value because we have turned off that default binding with use strict so ustrict turns off the global window object we don't have that by default and that's fine if you're using this you should understand what you're doing with this so if i call something with new or i call something with call or bind or apply i should understand what it is that i'm doing with that so there shouldn't be situations where i'm relying on this default behavior that's what ustrick does is it tries to teach you that you should intentionally do things in your code don't just rely on default behaviors okay arrow functions almost to the end here arrow functions as i was saying before they use lexical scope and that is the right time scope not the read time but the right time when it's going through the lexing when it's going through that tokenization that first pass where it's looking at where everything is written and determining what the scope is based on where it is written so if i create a function here and make it an arrow function there we go now i'm going to call this function and we'll give it a context let's just take one of our objects here let's say obj1 you would expect with a regular function we've done explicit binding which is number two on that list so with explicit binding this is going to be obj1 that's what it's going to write out but with arrow functions it goes back to that global object because with arrow functions we're looking at where is it written what is the context where the function was written so this is inside of this function right here what is the scope for this function it's the global object it's on the global namespace right here so therefore the window object is the scope and this even though we've got you strict up above with arrow functions we're not doing that default binding what we're doing is we're using lexical scope to determine this one other example with this one let's use a regular function that returns an arrow function just to further illustrate this point so our function will use our a1 object our obj1 object again it's got the a property we'll do that so here we're calling this function we're using obj1 as the context this is going to return another function now the one it's returning is an arrow function so i can call what came back this function right here gets passed back now because it's an arrow function we're using lexical scope with lexical it means we look at the function and we say hey what was what would the value of this be what is the context where you were written well in this case i called f6 with the context obj1 so we've got obj1 being the context that means when i run x which is this function i should get the value of obj1.a which is if we look up here 1. so that's the value that we should get from that there we are there is the one so that is working we're getting this obj1 context the other thing about error functions is that pardon me they ignore explicit binding they don't care about any other kind of binding they've been bound based on where they were written they use lexical scope so they care where they were written what the context was when they were written if you're using call like here i'm using call on a regular function but if i try to do x dot call and we say obj2 it doesn't care it does not care that we've said i want to use obj2 as the binding i still get one i still get obj1 as the binding because where this function was written the binding here the context here was obs1 so it doesn't matter what i pass in here with call that's the thing about arrow functions is they ignore explicit binding so the obj explicit binding is ignored and one last note about arrow functions they can't have their value of this changed they can't have a change by explicit binding they cannot be used as constructors they can't have their binding change so this isn't going to work so you're just going to get a type error if you try to run them as a constructor function you're just going to get that type error nothing's going to work all right so there is i think we got everything here we talked about constructors we talked about explicit binding we talked about implicit binding and a bunch of permutations of that use strict we talked about the default binding we talked about arrow functions we talked about in the last part event listeners in the browser this one's going to be easy now so down here what i did was i waited for the dom content loaded event i found all the paragraphs inside of main looped through them and i added a click handler to each one which is going to call this function right here now if i do v dot console.log target i'm going to get the reference to the paragraph here let me just comment these ones out here so i don't get a whole bunch of console log statements i think that was all of them that one right there okay there so we're empty now back down here so ev current target this is the paragraph that was clicked i've got three paragraphs on my page all three of them have click listeners all three of them will call this so if i click on this bottom one there's paragraph with the id three two one so every time i call them i know which paragraph it is that's clicked this is going to do the same thing this gives me the context so add event listener is the method being called what's the context for calling at event listener well it's this variable right here p and what is p it's this variable we're looping through all these paragraphs this represents each paragraph and turn as we're looping through it so this is going to give me the exact same value as ev.currenttarget so one two and three and there it is so that is lexical scope that is the key word this and all of its permutations i hope that clears up a lot of questions for you um if you have other questions about this feel free to leave them in the comments i'll answer as many as i have time for and as always thanks for watching
Info
Channel: Steve Griffith - Prof3ssorSt3v3
Views: 2,823
Rating: 4.9506173 out of 5
Keywords: MAD9014, MAD9022, web development, JavaScript, JS, HTML, steve flix, steveflix, web dev, mad9135, this, keyword this, javascript this, js this, lexical scope, tutorial about this, this tutorial, keyword this tutorial, what is lexical scope, lexical binding
Id: eWDXgsIgTGk
Channel Id: undefined
Length: 33min 1sec (1981 seconds)
Published: Mon Jul 27 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.