Let me now show you some pitfalls
of the this keyword related to regular functions
and arrow functions.
This way we can learn when we should use and avoid
each of them.
And to start, let's get back the Jonas object
from before,
and I will also add a first name property.
All right, and now let's add a second method here,
but this time using an arrow function.
So we will do a very simple greet method.
And so an arrow function here,
which simply logs to the console
Hey, and then the name.
And so we're gonna take this name from the object.
So this dot first name,
or at least, that's what we think we're doing.
So let me now show you what happens,
as I call jonas.greet.
And maybe you can also anticipate it based on the knowledge
that you already have off the this keywords
when used in an arrow function.
So let's see what the result is here.
And we get, Hey undefined.
So that's not Hey Jonas, as we might have expected.
And the reason is exactly the one that I mentioned
in the last lecture,
which is the fact that an arrow function
does not get its own this keyword,
it will simply use the this keyword from its surroundings.
So in other words, its parents this keyword,
and the parent scope of this greet method
is the global scope. Okay?
Just note here that this is actually not a code block.
So you might think that, like this kind of block here,
ought to create its own scope, but it doesn't.
So this is not a code block. It is an object literal.
So it's just a way that we literally define objects. Okay?
So all of this here is in the global scope still.
And so therefore, that includes this greet method.
It is in the global scope,
and so therefore, the arrow function here,
which does not have its own this keyword,
will use the this keyword from the global scope.
And remember that is the window object. Right?
And so this dot first name is also undefined.
And I think that this is actually something
that we haven't seen before.
So when we try to access a property that doesn't exist
on a certain object, we do not get an error,
but simply undefined.
And so that is what is happening here.
That's why we get undefined,
because this is the window object,
so just as we saw before, and then on the window object,
there is no first name, and so we get undefined. Okay?
And actually, this behavior can become pretty dangerous,
in case we use var, to declare variables.
Because remember from a previous lecture,
that variables declared with var, actually create properties
on the global object.
And so let's imagine we have this.
So var first name equals Matilda.
And so now as we run the greet function,
it will say, Hey Matilda, okay?
So why is that?
So again, it is because inside of this function here,
the this keyword is window.
And actually, let me print that here to the console as well,
just so we can really see that here happening. Okay.
So again, window is this keyword inside
of this arrow function, even though that arrow function
was called by the Jonas object.
But that rule does not apply here,
because again, it's an arrow function.
And so if we take a look at this window object now,
and here, close to F, for first name,
you see here, that it does indeed have a property
called first name with the value of Matilda.
And again, that's because if we declare variables with var,
that creates these kind of properties on the global object.
And so therefore, this dot first name,
which translates to window dot first name is then Matilda.
And so that's why we then get Hey Matilda here.
So that's yet another reason not to use var.
So you see there's a pretty long list against var.
So from this example, the big takeaway
is that as a best practice,
you should never ever use an arrow function as a method.
And in my opinion, that's even true if you're not even using
the this keyword in a particular method.
Because if you have this rule of never using an arrow
function as a method, then you never have to think about
which type of function you should use.
You will always just use a normal function expression,
and like this, you will then prevent this kind of mistakes
from happen.
So this mistake that we saw here with Hey Matilda
is easy to prevent by simply not using var.
But even then, Hey undefined is still a buck.
It's still not correct.
And so that would have easily been avoided
by just using a regular function. Right?
If we had this, then of course now this object Jonas,
which is calling the function
would then be the this keyword. Right?
So you see first name Jonas, and then Hey Jonas.
Because now this method actually does get its own
this keyword.
But let's put it back.
And, Okay. Great.
And now, one final example of a pitfall of this keyword
is when we have a function inside of a method.
And that is a pretty common thing to happen.
And so let's now take a look at an example of that.
So let's create another Jonas object here.
Or, actually don't.
Actually let's just use this object here
that we already have.
And let's enhance this calcAge method.
So what I want in here is a function
that will basically return if the person is a millennial.
So easy enough,
let's create an isMillennial function in here.
And let's simply log to the console,
if this dot year is greater equal 1981,
and so that's the same rule that we used before,
so that the birth year needs to stay between 1981 and 1996.
So below 1996.
And then let's also call that function right here.
So isMillennial will be called
as we called the calcAge function.
So let's also do that.
So Jonas dot calcAge
So we're calling this method here, the calcAge method,
which is a regular method, so not an arrow function.
And so therefore, the this keyword right here
should be the Jonas object.
But then in here, we have a regular function, so this one,
and here we are then calling it again.
Now inside of this function, we are using the this keyword.
And so let's now see what happens as we reload the page.
And we get cannot read property year of undefined
on line 138.
So that's right here.
So what this means is that the this keyword
must be undefined.
That's what it says here.
So let's just log that as well,
and here, we can get rid of this one now, okay.
And indeed, the this key word here is undefined.
So why is that?
Well, if we think about this, then this here
is really just a regular function call, isn't it?
It is a regular function call,
even though it happens inside of a method.
And the rule says that inside a regular function call,
which this clearly is, that this keyword must be undefined.
And so therefore it is undefined right here.
So this is just as if this function was outside
of this method.
So if we copy this function out here,
we would get the exact same result.
Now some people consider that this is a bug in JavaScript
but in my opinion, it's not really.
It's just how the this keyword works.
It's a clear rule that a regular function call
has the this keyword set to undefined.
And so that's just what is happening here.
Now there are two solutions to this problem.
The first solution is to use an extra variable
that we usually call self.
So outside of the function, let's say self
and then we set that to this.
Because here we are still outside
of this isMillennial function.
And so here, we still have access to this keyword
set to Jonas. Right?
And so then in here, we can use simply self.
And let's do that just here.
And here I will duplicate this line
so that we can keep the original one.
And so now let's use self here.
And so then through the scope chain,
this self will be equal to this.
So self is referenced here,
but it's not of course in the scope.
And so JavaScript goes up the scope chain,
into the parent scope, which is calcAge.
So here is where self is defined, and it is defined as this.
So as to this keyword.
And so this is a way in which we can preserve
the this keyword.
This can also be called debt, so that you might also see.
And so as we reload, now, this actually works.
So now we get the value of true.
So this was kind of the pre ES6 solution,
but you might still find this solution
in some older code bases.
However, now in ES6 we have a more modern
and better solution.
And that solution is to use an arrow function. Alright.
So let's actually copy all of this,
because I want to preserve both versions here.
And now I will just comment out this first.
Let's say solution one,
but now here we have solution two,
which does not need this extra variable.
Okay, so let's get rid of this
bring this back and here this again.
And now, again, the solution to the problem
that we saw before is that we can now use an arrow function.
And that is going to work because the arrow function
does not have its own this keyword. Right?
So let's remember again, that when we just call this,
we get that to this keyword is undefined.
And that's because a regular function
gets its own this keyword.
But the arrow function will not,
it will simply use this keyword of its parent scope.
And in this case, that will be the calcAge method,
and in here the this keyword is Jonas, so the Jonas object.
And therefore then here in an arrow function,
that would also be the this keyword.
And then it is gonna work as expected,
and indeed, now it is true.
And again, this worked because this arrow function
uses the this keyword from its parent scope.
And in this case, in the parent scope,
the this keyword is Jonas.
So basically an arrow function inherits the this keyword
from the parent scope.
And that is exactly what we need here. All right.
And so here, you see that it's pretty important
to know exactly how each of the different type of functions
work in regards to the this keyword.
Because then you can really use them according
to your specific needs.
Great. So I hope that especially this solution here
made sense to you.
And that when you need it at some point in your journey,
or in your job, you can remember that this is a very useful
use case of the arrow function.
Now, just to finish this lecture,
I also want to quickly touch on the arguments keywords.
Maybe you remember me talking about that,
also in a previous lecture.
So in the video about execution context,
and the call stack,
we learned that functions also get access
to an arguments keyword.
So not just the this keyword, but also an arguments keyword.
Now, just like the this keyword, the arguments keyword
is only available in regular functions.
So let's create another function here.
So first an expression.
So again, basically that's our functions for adding
and actually let me just grab them from here.
I think I defined them somewhere up here.
Yes.
So there's no need to rewrite
the same code over and over again.
Just add a comment here,
arguments keyword.
And then let me also print to the console, that keyword.
So let me quickly call this function here now.
So two and five
so just so we see the arguments keyword.
And so down here it is
and you see that we get basically an array
with two and five.
And so that's exactly the two parameters that we passed in.
And this can be useful when we need a function
to accept more parameters than we actually specified.
So this is something that we never did before.
So up until this point, we have only ever specified
exactly the arguments that we have here in the list
of parameters.
So we have two parameters, and so two arguments.
But it is completely legal to add more arguments.
They will not have a name, so we didn't name them,
but they exist.
And we can see them here in the arguments array. All right.
So they do appear here, and we can use them
therefore in the functions.
For example, we could use a loop,
and then loop over this array
and add all the numbers together.
But now my point here is that the arrow function
does not get this keyword.
So that's also log it to the console here
so let's put this here in curly braces,
then remember when we have more than one line of code,
we need to explicitly return.
And so let's try to take a look at the arguments keyword
here as well.
So add arrow two, five, eight, let's say,
but then we get an error.
So arguments is not defined. All right.
So this was simply just to show you
that the arguments keyword exists,
but that it only exists in regular functions.
So in function expressions like this,
but also in function declarations,
but not in an arrow function.
But anyway, the arguments keyword is not that important
in modern JavaScript anymore,
because now we have a more modern way
of dealing with multiple parameters.
But still it's important that you are aware
that this arguments keywords exists.
All right, and now with all these lectures
on regular functions and arrow functions,
you should know all the differences between them,
and even more importantly, when to use each of them.