Check out a free preview of the full The Hard Parts of Object Oriented JavaScript course
The "this Keyword Scoping Issues" Lesson is part of the full, The Hard Parts of Object Oriented JavaScript course featured in this preview video. Here's what you'd learn in this lesson:
The UserCreator.prototype.increment function is refactored further, and this poses an interesting problem with scope.
Transcript from the "this Keyword Scoping Issues" Lesson
[00:00:00]
>> Will Sentance: So let's do this again. We've had Nick and Chris walk through this. We're doing it one more time. Here we go, so no code is changed, people, except for the body of the increment function. Don't get confused, everything is the same, except for the body of the increment function.
[00:00:15]
So let's call, let's go back to our final line of code, user1.increment(), user1.increment(). Seth, talk me through the process.
>> Seth: It's going to attempt to look for increment on user1, it's not gonna find it. It's gonna freak out a little bit, but then it's gonna say, [CROSSTALK], okay, I found it in the prototype.
[00:00:35]
>> Will Sentance: Exactly. So you saw there that, Seth called it, I found it on the prototype. People do colloquially say, look to the prototype. Do you see why I don't like that? When it's referenced in the _proto_, that happens to be linking to an object that happens to be called prototype.
[00:00:51]
But we could redesign the new keyword to say. Make it leak, call this instead, I don't know, functionStore. And have the new keyword be redesigned to reference user created .functionStore. Prototype is not a magic word. Proto is a more powerful word in my view, and that's JavaScript automatically looks at Proto when it doesn't find.
[00:01:09]
And then it goes to this object, which happens to have the name Prototype, because that's where the bond was made. But we're gonna write that, in fact, we can literally overwrite that. We can manually later go user creator.funtionStore equals this object full of functions. And then we could put in here user1.__ or we can use separate type of.
[00:01:29]
We'll see that later. And put a different object or function here. There is nothing profound about prototype. It just happens to be the autodesignated place with the new keyword the link is made to. Okay, a little aside there. But there we go. We find increment and we create an execution context in which to run it.
[00:01:49]
Gonna try to make this a little bit bigger. Okay, there it is. And in it's local memory, Seth, what is the first assignment that automatically happens? There's no argument parameters, but there is a implicit parameter, as they're known.
>> Seth: This becomes user1.
>> Will Sentance: This becomes user1, fantastic, next?
[00:02:07]
>> Seth: There's a new function called add one.
>> Will Sentance: Fantastic yeah add one, store it, and then we immediately call it. So give me a second, so add one. It creates a new.
>> Seth: Execution context.
>> Will Sentance: Fantastic Seth, into it we go.
>> Seth: This gets assigned to.
>> Will Sentance: Okay excellent so what does this get assigned to here?
[00:02:28]
Michael?
>> Michael: I mean the function is at one so it's an anonymous function.
>> Seth: It gets assigned an increment window.
>> Will Sentance: So lots of nice suggestions. Susie? Yeah absolutely, who knows? Cuz I told you one simple rule, that this is assigned to the object to the left hand side of the dot, I don't see any object to the left hand side of the dot here, so what does it default to?
[00:02:50]
>> David: Window.
>> Will Sentance: Window as David says, all the way to this random ass window object thing. So there it is, this is assigned to Window, whatever that is. [INAUDIBLE] this is an object with all the features of JavaScript in. So, let's see what I have, this.score++ is actually gonna say window.score++, we're gonna end up on our funny old window object thing, a property called score with property not a number.
[00:03:23]
Because this should be undefined right? And then you try to add one to it, you get N A N. This is hopeless and yet for an object already to programming having sub-methods. I don't know what you call them, sorry sub-functions with in a method Is absolutely appropriate because this increment method has only got one line, but often you've got 50, 100 lines.
[00:03:45]
You want to organize that into some functions. But if you do, and refer to the this, unlike any sane language, I love JavaScript, but this, in traditional languages would look at this and frown. The this does not point to the object which is obviously the pertinent object, but it's by design.
[00:04:08]
In JavaScript, the this is only assigned to the object to the left of the dot. There ain't no left of the dot here. So there were old ways of solving this, which some of you may be familiar with. People used to say okay, well, here, that equals this.
[00:04:25]
And then, that would point to the user 1 object and then here we'd refer, not to this .score++, but that .score++. Does anybody think that's a good design decision? Apparently, it's quite efficient. Apparently, it's actually quite efficient of a performance. I don't know why. But alternative would be to use bind, core, apply.
[00:04:47]
We'll see those in a moment. But I think now the standard approach is to use. Well, who knows, Seth?
>> Seth: Add on the prototype, wouldn't you?
>> Will Sentance: Anyone know what the, Steve?
>> Steve: I can't remember.
>> Will Sentance: There's a new way of declaring functions that when they're called, they're this inside of them.
[00:05:05]
>> Seth: Arrow function.
>> Will Sentance: Arrow functions, exactly. The reason they rebranded from fat arrow functions just to arrow functions, because there was no need for them to be called fat arrow functions apparently. So, before we see those I wanna make really clear cause you never see me declare functions this way, I wanna make, what are not sort of arrow functions but you'll never see me declare functions this way, but I wanna make really clear that this line here, the blurred out line add one is a function.
[00:05:30]
I wanna make clear, that is an identical, for our purposes it's a hoisting thing, but ignore that for now. It is an identical function declaration to the one above. See function Add1, store the function Add1. That next line there says Add1 is a label for the function that has the code this.score++.
[00:05:48]
I just wanna make sure everyone gets that is identical function. The one is called function expression and the one I always use is called function declaration, but they're identical. Just because in a moment, you gonna see an arrow function, which looks a lot like the second one, but I don't want you to think it's some sort of special different function.
[00:06:05]
So let's switch this up, rather than declaring a function Add1, using the traditional function declaration or expression, neither of which give us the right this assignment inside, and leaves us doing silly stuff like that equals this, which was really, really standard people, it was absolutely standard and very strange.
[00:06:26]
Instead we get a new way of declaring the add one function such that when it's called, it's this assignment is automatically what's called static or scoped. That means it's going to automatically refer to the this from where it was born. If any of you have seen closure hard parts you know how important where I save my function is in JavaScript.
[00:06:51]
Well with these arrow function it's super important. Where I call it, the this will be the same as where the function was saved, where it was fined, and that's gonna solve our whole problem. So let's just walk through it. And then we're gonna get solution four, but as a nice little interlude I want to give us to save us from the biggest gotcha in OOP, that was the biggest gotcha, calling functions inside a method, and it referring to nothing that we wanted, the this being miss assigned.
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops