Jonas: Welcome to the next lecture.
Let's continue with arrow functions,
and see another reason why they are so useful.
So, maybe the biggest advantage of using arrow functions
is that they share the surrounding this keyword.
So, this means that, unlike normal functions,
arrow functions don't get their own this keyword.
So, again, arrow functions do not have a this keyword.
They simply use the this keyword
of the function they are written in.
And so we say that they have a lexical this variable.
So let's now see how we can
actually use that to our advantage.
And now we're going to use
one of these boxes here for the first time.
So, let's write an object with some properties,
and then we will have also a function,
which will attach an event handler to this box here.
Okay?
So let's do that.
And, once again, I'm gonna start by writing
the ES5 version of this.
So let's call this object box, and box5.
And we're gonna say the first property is color,
and it's green.
Okay, so, we're talking about
this very first box here, okay?
This, of course, is a comma.
And the position of that box is number one, all right?
So it's the first one.
And then we also want a method here, called clickMe.
And let's just add a function.
All right.
Now, what we want this method to do
is to simply attach an event handler to this element here.
So let's just quickly jump into our HTML file
and see that it's this one.
So it's with the class of green, okay?
So, how do we add an event handler?
We say, document.querySelector, right,
to first selected element.
And then, addEventListener.
And we want it to happen on a click,
because that's the easiest one.
And then we add our callback, right?
And we actually want something very simple here.
All we want is to have an alert
which says the color of the box, so, in this case, green,
so it's stored in here, and the position,
which is stored here.
So, let's start by creating a string.
So, I'm just gonna call this string str.
This
is box number, and since we're writing ES5 here,
I'm actually gonna do it entirely in ES5,
and so I'm gonna use the plus sign here
instead of the template literal.
Okay.
So, I say,
this.position.
So, box number one.
And it is,
and then the color.
All right.
And then we can alert this string.
Okay.
So, let's now call this method.
So, box5.clickMe.
And as soon as this method is executed, is called,
the event listener will be added to this element.
So, let's reload this.
Now, do you think that this is really gonna happen
the way that we intended it to work?
Let's check it out.
So I'm now going to click on this box here.
And it says, this is box number undefined
and it's undefined.
Okay, so, why is this happening?
Why is it not reading our values from this object here?
So, green and one.
And the reason for that is something that I said
in the very beginning of the course,
and that is, that only the method call,
the this keyword, actually points to that object.
But in a regular function call, the this keyword
will always point to the global object,
which, in the case of the browser, is the window object.
And that is exactly what happens here.
So, this clickMe method is a function attached to an object.
So it's a method, and so in here,
we have access to the color and to position
by using the this keyword, right?
But then, this callback function that we have here
and this event handler here is not a method,
it's a regular function call, and therefore,
the this keyword here does not point to this box5 object,
but instead, it points to the window object.
And, of course, position and color
are not defined in the window object.
And therefore, what we have here
is undefined for both of these.
So, some say that this is a bug in JavaScript,
and others say that this is actually how it should behave.
Now, a very common pattern to avoid this
is to simply create a new variable in here
and store the this variable in that new variable.
So let's try that out.
So let's say, var,
and we usually use a variable called self, or that,
and I prefer to call it self.
And so we simply say self
equals this.
And then the self variable points to this.
And so, in here, instead of using this, we use self.
And then we basically stored the this variable here
in this new variable, so that we can then use it
in the rest of the function.
So, this is kind of a workaround, kind of a hack,
to avoid the situation that, in this function call here,
we don't have access to the box5 object.
Okay?
So let's now run this again, click here, and now it works.
Now it says, this is box number one and it's green.
All right.
So, remember that in the beginning I said
that with arrow functions, they actually share
the surrounding this keyword.
So let's see how we can use arrow functions
in order to avoid this hack here, right?
So let me just go ahead and copy all of this, actually.
There is no need to write it all again.
So, it's ES6 now, I'm gonna call it box6,
and call box6 here, and now,
it's not a var, it's a constant.
So, let's say const.
And we don't use this,
okay?
Because now, what we're gonna do here
is to use an arrow function
instead of this anonymous function here.
So let's get rid of this.
And remember that when we don't have any arguments
or if we have more than one argument,
we have to specify the parenthesis.
So we do that, then the arrow,
and then our function body, which is this.
And it's actually as simple as this.
So now, in here we have a function
that shares the this keyword with its surrounding,
so, with the clickMe method here.
And we know that in here, the this keyword
points to the object.
So now, in here, we can actually use the this keyword.
Right?
So let's get rid of this one here.
And let's run it.
And I'm gonna click now and here it is.
So, this is box number one and it's green.
So now, by using the arrow function,
we really have access to the this keyword
of this method here, because, again,
the arrow function shares the lexical this keyword
of its surroundings.
So, if you want to start using ES6
and arrow functions today,
then the best practice is to actually
always use arrow functions when you need to preserve
the value of the this keyword, such as we did here.
So, using arrow functions here was very useful, right?
Let me just show you another scenario here.
Let me copy this again,
and get rid of this one,
and this is the ES6, let's call this 66 now, okay.
So in here, we still have a function
that we could potentially replace
with an arrow function, right?
And it's this one.
So, if I, instead of this function expression,
I wanted to write an arrow,
I could simply do it like this, right?
It would work the exact same thing.
But let's see if the result is still the one that we want.
So, reload, and now I click here.
And now it says undefined again, and why is that?
And it's actually very simple.
And it's because this method here does now
also share the lexical this keyword from its surroundings.
And the surrounding of this is the global context, right?
So this means that this method here
also no longer has its own this keyword.
So it shares the global this keyword,
which, of course, points to the global object window.
So this is the same situation as right in the beginning.
We don't have position and color in the window, right?
And, therefore, it becomes undefined.
So, this is not something that we want,
but I just wanted to show you
that you have to be really careful
with these arrow functions, so that you don't lose track
of what the this keyword actually points to.
So, I will just comment this one out,
because it's not really interesting for us.
So, again, I just wanted to show you to be careful.
All right, and since this is
one of the really great new things in JavaScript,
let me just show you another example,
because I really, really like these arrow functions.
So we'll have another example here.
Let's create a function constructor
in order to create a Person object, okay?
So, once again, we've done that a lot of times before.
So you already know how to do this.
And I'm gonna keep it very simple, just with the name.
So, this.name is, of course, the name.
And let's now add a method
to the prototype property of the Person
so the object created through
the Person function constructor
inherit this method.
So, once again, nothing new here.
So, Person.prototype property,
and then let's say, myFriends.
And, once again, it's myFriends5,
because we're using ES5, in this case, first,
so that I can show you the first example with ES5
and the second one with ES6.
So, this is a function
which actually receives an array of friends,
and what we want to do here
is to simply return an array which says
that the name of the person is friends
with each of these elements
that are in this friends array, right?
So, imagine that the person is John,
and that the friends are Bob and Jane.
Then we want to say, John is friends with Bob,
and John is friends with Jane, okay?
So let's create an array.
Simply call it arr.
And then we're gonna use the map method
that we used before once again.
And this time, here, on the friends array.
All right.
So, you already know that we
could use the arrow function here,
but since I'm writing ES5, I'm just gonna do it this way.
So, we have access to the current element,
and so I'm gonna call it el,
which stands for element.
And so in each element of this array,
all I want is to say the name of the person
is friends
with, and then, of course,
the current element, which is called el.
Okay, and then we simply can console.log
the array.
All right.
Let's now create a couple of friends.
Bob,
Jane,
and Mark, let's say.
That should be enough for now.
So let's create a new Person,
called John.
And then we can call right away
the myFriends5 method.
And we're gonna pass the friends into it, of course.
All right.
So, again, do you think that this is going to work?
Take a deep look at this method here
and see if the this variable will actually point
to what we think it points.
Okay?
So, let's now run this.
And, actually, something weird happens.
So, the name is not defined.
And this is because of the exact same reason as before.
So, in here, in this method,
we of course have access to the this variable,
and it points to the name of the person,
so it would be John.
But the thing is that, in here,
we call another function, right?
Which is this anonymous function.
And so, in here, the this keyword
is not going to point to the object,
but, instead, it's going to point to the global object,
which is window, once again.
Now we could, again, use that trick that we used before
by saying var self equal this,
so, basically storing the this variable
in a separate variable, but I just want to show you
another cool trick that we could use here instead.
So, remember that we have to bind call and apply methods,
which we can use to set the this keyword, right?
Remember that part?
So, call, bind, and apply allow us to
define the this variable manually,
and bind creates a copy of this function,
while call actually calls it immediately, okay?
So, what we can do here is to create a copy of this function
with the this variable set to this.
So, this here is the function, right?
And so in this function, we can create
a copy of this function using the bind method, right here.
So, what we want the this keyword in here to be?
Exactly, we want it to be this.
So, this maybe sounds or looks a little bit weird,
but this is actually going to work.
Because, remember, here, outside,
we still have access to the this variable,
and it points to the new person,
so, in this case, it would be John.
And so we can basically pass it
into this function here simply by creating
a new copy of the function
with a manually-defined this keyword.
So let's check if this works now.
And, yes, it does.
So, John is friends with Bob, with Jane, and with Mark.
So, this is the ES5 version.
And you still learned a very cool trick
with this bind here, right?
All right, and now, the ES6 version.
And, once again, I'm going to copy it
and just modify some stuff.
So this one is called myFriends6,
and then in here, we can change the content of our method.
Now, I want you to go ahead on your own
and change everything here,
so that we no longer need this trick here.
And I'm sure that you can do that by now, right?
So, please pause the video and do that right now.
So, I'm sure that you managed to do it,
so let me show you my solution.
So, of course, we used an arrow function here, right?
And we actually don't need any of this, right?
Because we simply have one line of code.
So what I'm gonna do is copy this,
delete all of this, and just paste it back here.
And another thing that we can do
is to use a template string,
which is way cooler than doing it this way.
So, we get rid of all of this.
So I'm missing the backticks here, okay?
And here we go.
So now we have transformed this to an arrow function,
and so, as you learned before,
this function does not have its own this keyword,
and therefore, we share the lexical this keyword
from our surroundings.
And the surroundings is, in this case, of course,
this method, where the this variable
points exactly to the point where we want,
which is the instance that we create.
So let's create a new instance,
and then the this keyword will point to it.
This time, let's call it Mike.
Okay?
And then Friends6 here, of course.
And let's see that it's gonna work.
And, actually, it doesn't, and that's because
I didn't copy the new operator, right?
So we were simply doing a function call
with the Person, instead of creating a new object.
So, let's try it again, and now it works.
Mike is friends with Bob, Mike, Jane, and Mike, Mark.
Okay.
So, once again, we used the power
of the arrow function here.
So, I hope that these two lectures
were enough to really convince you
to start using the arrow functions.
I hope that everything makes a lot of sense to you
up until this point, and if it does,
then let's go right now to the next lecture,
which is gonna be about destructuring,
so, another new concept in ES6.
So let's move on.