Coding

JS “this” and Function References – What is it all about?

  • 00:00:01 welcome to this video in this video I
  • 00:00:04 want to talk about something or tackle
  • 00:00:06 something which I saw in a lot of
  • 00:00:07 comments and also in some of my courses
  • 00:00:09 that it can be hard to grasp to
  • 00:00:11 understand and that is the usage of the
  • 00:00:14 this keyword in JavaScript and why it
  • 00:00:17 can behave strangely in some cases and
  • 00:00:19 it's also that when you call a function
  • 00:00:22 or a method sometimes you omit the
  • 00:00:25 parentheses after the function name and
  • 00:00:28 I want to talk about that queue and
  • 00:00:30 explain when you call a function with
  • 00:00:32 parentheses and when you use it without
  • 00:00:35 these so two important things which I
  • 00:00:37 see that they can lead to a lot of
  • 00:00:40 confusion hopefully this video can
  • 00:00:42 clarify these things
  • 00:00:47 now for this video we need a tiny demo
  • 00:00:50 project to get started and you can find
  • 00:00:52 it attached to this video so to say
  • 00:00:54 below the video you'll find a link to a
  • 00:00:56 github repository with this very simple
  • 00:00:59 dummy project there we got a HTML file
  • 00:01:02 with a html5 skeleton in the body I got
  • 00:01:06 a button saying add name
  • 00:01:08 I got an unordered list with no content
  • 00:01:10 but with that ID of names and I'm
  • 00:01:13 importing my app.js
  • 00:01:15 script which is this script of course in
  • 00:01:17 there we got an error which we'll fix of
  • 00:01:19 course in this video and besides that we
  • 00:01:22 get this code now here I'm using
  • 00:01:24 JavaScript classes in case you're not
  • 00:01:26 used to using classes in JavaScript you
  • 00:01:29 probably know constructor functions
  • 00:01:32 constructor functions are normal
  • 00:01:34 functions which you can call to create
  • 00:01:36 new object and initialize them with some
  • 00:01:38 properties and methods so I'm talking
  • 00:01:40 about object orientated JavaScript
  • 00:01:42 development and we need objects to
  • 00:01:45 understand and use the this keyword that
  • 00:01:47 is why I opted for the next-gen syntax
  • 00:01:50 using that es6 feature of classes now
  • 00:01:53 you can also take my es6 course and all
  • 00:01:56 my accelerated JavaScript first fewer
  • 00:01:58 and more about constructor functions and
  • 00:02:00 in the year six course you'll learn
  • 00:02:01 about classes here I assume you know
  • 00:02:04 what classes do in the end they serve as
  • 00:02:06 blueprints for us to create new objects
  • 00:02:09 we do that with the new keyword this
  • 00:02:11 creates a new object in this case we
  • 00:02:13 store it in Gen and then don't do
  • 00:02:15 anything with that object then because
  • 00:02:17 name generator' which is the blueprint
  • 00:02:19 or the class for that object I'm
  • 00:02:21 creating has a constructor which gets
  • 00:02:23 called when I call new and then the code
  • 00:02:25 and here basically just gets a reference
  • 00:02:27 to my button by using the button tag as
  • 00:02:30 a selector and then I attach the event
  • 00:02:32 listener for the click event and then
  • 00:02:34 we'll need to fill this blank to tell
  • 00:02:37 JavaScript which code to execute when a
  • 00:02:40 click occurs then I also get a method in
  • 00:02:43 this class here a method is just a
  • 00:02:46 function in a class you could say it's
  • 00:02:48 called add name and in there I create a
  • 00:02:51 new instance off the name field class so
  • 00:02:54 I create a new object again I don't do
  • 00:02:56 anything with that object but one thing
  • 00:02:59 I do is I create
  • 00:03:00 here we get a constructor and in that
  • 00:03:03 constructor I simply create a new list
  • 00:03:04 item I then whoops set some text to that
  • 00:03:09 list item the text is the argument I'm
  • 00:03:11 getting here essentially the name which
  • 00:03:14 I want to output and the name is passed
  • 00:03:16 here right now it's always max I'll
  • 00:03:18 change this and then I get a reference
  • 00:03:21 to my unordered list with that ID
  • 00:03:24 selector using that names ID here and I
  • 00:03:27 add that name now let's make this work
  • 00:03:32 by first of all removing these free
  • 00:03:34 question marks and here I obviously want
  • 00:03:37 to call add name I want to execute that
  • 00:03:39 add name method now for this we already
  • 00:03:42 need to use the two things this video is
  • 00:03:44 about this and we also need to use or
  • 00:03:49 call a function in a special way you
  • 00:03:51 could say because here I want to execute
  • 00:03:54 add name and you could think we just
  • 00:03:56 specify add name like this this would be
  • 00:03:59 wrong due to two reasons first of all if
  • 00:04:03 we specify like this JavaScript would
  • 00:04:05 look for a variable called add name or a
  • 00:04:08 function called add name in the scope of
  • 00:04:11 this constructor and if it doesn't find
  • 00:04:14 it there in the global scope in the
  • 00:04:16 overall file you could say in the on the
  • 00:04:18 whole window to which this script is
  • 00:04:21 attached now we got no add name variable
  • 00:04:24 or function in the constructor and we
  • 00:04:26 also got anon in the overall file or
  • 00:04:28 anywhere else in this app so this will
  • 00:04:30 not work and I can prove this to you if
  • 00:04:32 we save that and I open my developer
  • 00:04:34 tools here and I reload this page we
  • 00:04:37 already see add name is not defined
  • 00:04:40 because it doesn't find it because a
  • 00:04:43 method what we have here is attached to
  • 00:04:46 this object so to this class and
  • 00:04:48 therefore to the object we create based
  • 00:04:50 on the class if we want to tell
  • 00:04:52 JavaScript that I want to access
  • 00:04:55 function that is attached to the class
  • 00:04:57 so to say we need that special this
  • 00:05:00 keyword this essentially refers Judah
  • 00:05:03 object the code is in so here this line
  • 00:05:07 of code is in this object in the name
  • 00:05:09 generator so if you want to refer to
  • 00:05:11 anything else that is attached to the
  • 00:05:13 name generator like
  • 00:05:14 at name we need to prepend this and then
  • 00:05:17 dot because this essentially gives us
  • 00:05:20 access to this object and that we can
  • 00:05:22 call methods or access properties on
  • 00:05:24 that object with the dot notation so ad
  • 00:05:27 name now it calls dysfunction on this
  • 00:05:30 object this is how we can use this we're
  • 00:05:33 still not there though if I save this
  • 00:05:36 and I reload hmm I get max here without
  • 00:05:40 me touching that button on the other end
  • 00:05:42 if I do click the button nothing happens
  • 00:05:44 and we also get no error which makes
  • 00:05:47 that super hard to debug of course now
  • 00:05:50 the problem we got here is this function
  • 00:05:53 gets executed immediately and why is
  • 00:05:57 that because I have parentheses here
  • 00:06:00 what happens is JavaScript reads that
  • 00:06:03 code from top to bottom and it does read
  • 00:06:06 and parse that code when the script gets
  • 00:06:08 first executed which happens when the
  • 00:06:11 browser parses this HTML file and
  • 00:06:13 reaches the script import it then
  • 00:06:15 immediately goes to the script file and
  • 00:06:17 parses dead this is important because
  • 00:06:19 this allows us to start our scripts when
  • 00:06:22 the page is loaded and load everything
  • 00:06:23 into memory and let the browser do its
  • 00:06:26 job however as it goes through that file
  • 00:06:30 it all defines this line and here what I
  • 00:06:34 do is I simply execute a function this
  • 00:06:37 is how I execute a function right I use
  • 00:06:39 the function name and the fact that it's
  • 00:06:41 a method here because it's attached to a
  • 00:06:43 class it doesn't change that I use the
  • 00:06:45 function or method name I add
  • 00:06:47 parentheses I could pass any arguments
  • 00:06:50 if that function would accept any and
  • 00:06:52 we're done this executes a function the
  • 00:06:55 problem is here I don't want to execute
  • 00:06:58 it immediately when I wanted to in
  • 00:06:59 status I just want to tell JavaScript
  • 00:07:02 that it should register this event
  • 00:07:05 listener and eventually execute this
  • 00:07:08 function when that click occurs so not
  • 00:07:11 immediately only when that click occurs
  • 00:07:13 and to do that I remove these
  • 00:07:16 parentheses so the two parentheses I had
  • 00:07:20 after add name if I now save this and I
  • 00:07:23 reload we don't see Mac's right from the
  • 00:07:25 start but if I click the button
  • 00:07:28 now I'm adding my list items now why is
  • 00:07:31 that because my right now what I'm doing
  • 00:07:34 is I'm just passing a reference to my
  • 00:07:37 function so like an address you could
  • 00:07:39 say to that event listener so I'm
  • 00:07:42 basically just telling JavaScript hey
  • 00:07:44 here is the address of the function or
  • 00:07:47 method you should execute when they
  • 00:07:50 click occurs so that you know where to
  • 00:07:52 find it when you need to call it because
  • 00:07:54 we don't call that function on our own
  • 00:07:57 JavaScript does that so to say the
  • 00:07:59 browser does that it does that when the
  • 00:08:02 click occurs that is exactly what we're
  • 00:08:04 setting up here so we just passed the
  • 00:08:06 address to the function with parentheses
  • 00:08:09 like this we would execute it
  • 00:08:11 immediately we don't want to do that
  • 00:08:13 therefore without parentheses we just
  • 00:08:17 passed the reference the address of the
  • 00:08:19 function to the code which should be
  • 00:08:21 aware of it and which should execute it
  • 00:08:23 when the time is used so when we click
  • 00:08:25 this is the important concept here that
  • 00:08:28 we're just passing the reference that
  • 00:08:30 we're just passing the address to the
  • 00:08:32 function and this is perfectly valid and
  • 00:08:34 normal JavaScript code this is no
  • 00:08:36 workaround or trick or a hack or
  • 00:08:37 anything like that this is a normal way
  • 00:08:39 of doing that now this is working
  • 00:08:43 now let's tweak that code a little bit
  • 00:08:45 because this can actually behave
  • 00:08:47 strangely right now it doesn't but it
  • 00:08:49 can let's say that in this class here we
  • 00:08:53 want to manage a list of names and cycle
  • 00:08:57 through these names so we could have
  • 00:08:59 something like names and that is an
  • 00:09:02 array let's say and in there i got max I
  • 00:09:06 got my colleague menu and I got an ax so
  • 00:09:09 I got these three names and my idea is
  • 00:09:11 that for every click I want to output a
  • 00:09:13 different name now to do that I need to
  • 00:09:16 get access to my name's an add name
  • 00:09:18 because that is ultimately where I pass
  • 00:09:20 the name – name field now obviously one
  • 00:09:24 easy workaround would be to simply move
  • 00:09:25 that constant down there but let's
  • 00:09:28 pretend we need that in other places of
  • 00:09:30 this name generator class – in that case
  • 00:09:34 I want to manage it globally simply like
  • 00:09:37 that method is available from anywhere
  • 00:09:39 in this class – with this
  • 00:09:41 I want to make my name's available from
  • 00:09:44 anywhere in this class and therefore I
  • 00:09:46 can create a property of field named
  • 00:09:50 names and I do this by adding this dot
  • 00:09:52 at the beginning and what this does is
  • 00:09:54 it's now not a constant or variable
  • 00:09:57 anymore instead you could say it's a
  • 00:09:59 variable attached to this class a so
  • 00:10:02 called property or field so now this
  • 00:10:05 names can be used from anywhere inside
  • 00:10:08 this class and by the way although only
  • 00:10:11 instantiated object there we can call
  • 00:10:14 add name because it's part of the class
  • 00:10:17 and we can access names because it's
  • 00:10:19 part of that class due to that this
  • 00:10:21 keyword so this really combines or
  • 00:10:25 attaches things to the entire class and
  • 00:10:27 therefore to the entire object which
  • 00:10:29 gets created and what this allows me to
  • 00:10:31 do is I can now access this names down
  • 00:10:35 there and now here an add name I'm
  • 00:10:38 referring to my array of names which I'm
  • 00:10:40 setting up in a constructor and this is
  • 00:10:42 how we initialize a property or field in
  • 00:10:45 a constructor and how we then use it
  • 00:10:46 somewhere else
  • 00:10:47 however I of course don't just want to
  • 00:10:50 use the entire array down there I want
  • 00:10:52 to cycle through my names so add another
  • 00:10:54 property and I'll name it current name
  • 00:10:56 the names of these properties are of
  • 00:10:59 course up to you and I'll set this equal
  • 00:11:01 to a number zero because index starts at
  • 00:11:05 index zero and I want to start with name
  • 00:11:07 first because now what I can do is I can
  • 00:11:09 access the first element with this
  • 00:11:11 current name so current name is null is
  • 00:11:14 zero initially so I access the first
  • 00:11:17 element in my array here down there
  • 00:11:19 first array element is Max and I passed
  • 00:11:22 that name field now of course I want to
  • 00:11:24 change current name with every click so
  • 00:11:27 after creating the name field I can set
  • 00:11:30 current name to current name plus one
  • 00:11:33 with that plus plus shortcut we only got
  • 00:11:36 three elements in the array so what I
  • 00:11:38 want to check here is if this current
  • 00:11:42 name is greater than this names length
  • 00:11:47 then I need to reset it because then we
  • 00:11:51 exceeded the array now actually this is
  • 00:11:54 not
  • 00:11:55 correct check because the length of this
  • 00:11:58 array will be free and I actually
  • 00:12:00 already exceeded or exhausted the entire
  • 00:12:03 array if current name is two because the
  • 00:12:06 index starts at zero if current name is
  • 00:12:08 two will have extracted the name Ana so
  • 00:12:11 therefore I actually want to convert
  • 00:12:13 this to greater than or equal to length
  • 00:12:15 length is free and if we incremented
  • 00:12:18 current name to free we know we don't
  • 00:12:20 have a element for that
  • 00:12:21 so let's reset it now let's see if that
  • 00:12:25 works if I reload and I click add name
  • 00:12:28 hmm I get an error and the error is that
  • 00:12:31 I cannot read the property and the find
  • 00:12:33 of undefined and it occurs in line 19
  • 00:12:37 now line 19 is this line where I try to
  • 00:12:40 use names and current name and do you
  • 00:12:43 have any idea what's the issue here now
  • 00:12:47 in theory that code should work but now
  • 00:12:49 we got a special thing of the this
  • 00:12:52 keyword this does not always refer to
  • 00:12:57 the surrounding object so to say to the
  • 00:13:00 class it's generally what it refers to
  • 00:13:04 you could say in most cases but actually
  • 00:13:07 this is to find a bit differently in
  • 00:13:08 JavaScript this refers to whoever called
  • 00:13:14 the function in which you use this so an
  • 00:13:18 add name we're using this and now who
  • 00:13:21 did call or what's responsible for
  • 00:13:23 executing this function this is not this
  • 00:13:26 class indirectly it is but not directly
  • 00:13:29 directly the responsible thing is our
  • 00:13:33 button event here and we can show this
  • 00:13:36 by console logging this let's look into
  • 00:13:39 this let's see what this is when we
  • 00:13:41 execute add name if I click here we see
  • 00:13:44 it's the button so the button is this
  • 00:13:48 here and that is the case because this
  • 00:13:52 event listener and therefore the button
  • 00:13:55 is executing our function when we click
  • 00:13:58 we pass the address to the function to
  • 00:14:01 the button or to the event listener and
  • 00:14:03 we say execute the function for us when
  • 00:14:06 a click occurs and then this simple
  • 00:14:09 first to the button this is how it works
  • 00:14:10 in JavaScript it's not always the object
  • 00:14:13 in which you write your code it's the
  • 00:14:15 thing which calls your code which
  • 00:14:16 executes your code you could say and
  • 00:14:18 that method gets executed by the button
  • 00:14:20 when a click occurs just to prove this
  • 00:14:24 if I console.log this in a constructor
  • 00:14:27 here then we see there it's referring to
  • 00:14:31 the name generator object to the class
  • 00:14:33 to the constructor function and that is
  • 00:14:36 the case because this code here is not
  • 00:14:39 executed by the button or anything like
  • 00:14:41 that it's simply parsed by JavaScript
  • 00:14:43 from top to bottom and therefore this
  • 00:14:45 then refers to the class to the object
  • 00:14:47 that surrounds it this can be hard to
  • 00:14:50 understand and the end it is just
  • 00:14:52 something you can memorize this refers
  • 00:14:54 to what's executing the code and here
  • 00:14:57 the so here in the constructor the what
  • 00:14:59 is executing the code is simply just
  • 00:15:02 well here this line in the end this is
  • 00:15:04 calling the constructor and therefore
  • 00:15:06 here we call the code and this in here
  • 00:15:10 refers to the constructor now for add
  • 00:15:14 name the button calls add name and this
  • 00:15:16 then refers to the button and not to
  • 00:15:19 this class anymore on the other hand if
  • 00:15:21 we would call add name here directly and
  • 00:15:24 not wait for a button click so we
  • 00:15:26 executed the constructor here and I
  • 00:15:29 reload then you see it works and this
  • 00:15:31 actually also refers to the name
  • 00:15:33 generator the reason for this is that we
  • 00:15:34 again execute the code in the scope of
  • 00:15:37 this constructor therefore the
  • 00:15:39 constructor and therefore the class is
  • 00:15:41 executing this line so this refers to
  • 00:15:43 who executed it and that is our
  • 00:15:46 constructor and therefore the class this
  • 00:15:48 is how this works now how can we change
  • 00:15:51 that behavior one way of changing it is
  • 00:15:55 to use a special method we can call and
  • 00:15:58 that is a method we can call on any
  • 00:16:00 function it's the bind function bind
  • 00:16:04 actually allows us to tell JavaScript
  • 00:16:06 what this should be referring to in the
  • 00:16:10 function that will eventually get
  • 00:16:12 executed so born still does not
  • 00:16:14 immediately execute the function we keep
  • 00:16:17 that behavior of just passing the
  • 00:16:18 address but we configured a function for
  • 00:16:21 the time when it
  • 00:16:22 we'll get executed so to say and we do
  • 00:16:24 so with the first argument by telling it
  • 00:16:26 what should this refer to in the
  • 00:16:30 function when it gets executed in the
  • 00:16:32 future no matter who executes it
  • 00:16:34 and if I find this year I'm telling
  • 00:16:37 JavaScript that this incite this method
  • 00:16:40 should refer to the same thing this
  • 00:16:43 refers to in a constructor and as we
  • 00:16:46 just saw with console.log in the
  • 00:16:48 constructor this refers to the class and
  • 00:16:51 not to the button so here I'm telling
  • 00:16:54 JavaScript no matter who executes this
  • 00:16:57 add name this inside of that name should
  • 00:17:01 always refer to this in the constructor
  • 00:17:05 to whatever this is and this and the
  • 00:17:07 constructor simply is our class because
  • 00:17:09 we're calling our constructor down there
  • 00:17:12 this is one way of ensuring that this
  • 00:17:15 code down there will work if I now save
  • 00:17:18 this and I reload you see I can cycle
  • 00:17:22 through my names and output them there
  • 00:17:24 and now this works as intended and I
  • 00:17:26 know that this can be hard to wrap your
  • 00:17:28 head around it's a special thing and in
  • 00:17:30 the end if you encounter any issues with
  • 00:17:33 you using this and suddenly it doesn't
  • 00:17:35 work check if your may be calling your
  • 00:17:39 function indirectly through some event
  • 00:17:41 listener or anything like that and
  • 00:17:43 therefore this and a function that gets
  • 00:17:45 executed might not be referring to your
  • 00:17:47 object anymore now when our way of
  • 00:17:51 solving this by the way is that you pass
  • 00:17:53 an anonymous function here and that
  • 00:17:56 anonymous function has to be an arrow
  • 00:17:57 function let's first of all use a normal
  • 00:17:59 anonymous function so I have I define a
  • 00:18:02 function in place this function here is
  • 00:18:05 not executed immediately it's just a
  • 00:18:08 find and it will still be executed by
  • 00:18:10 the click listener and in there I can of
  • 00:18:12 course call add name this add name like
  • 00:18:16 this now this line again will not be
  • 00:18:18 executed immediately
  • 00:18:19 because this is executed immediately but
  • 00:18:22 the code in this function is not instead
  • 00:18:24 this code being executed immediately
  • 00:18:26 just registers the function in memory
  • 00:18:28 and passes it to the event listener so
  • 00:18:31 if I save this you see nothing gets
  • 00:18:33 rendered so this add name is not
  • 00:18:36 executed immediately but clicking on add
  • 00:18:38 name gives us another issue that add
  • 00:18:42 name this add name is not a function and
  • 00:18:44 the reason for this is that again this
  • 00:18:46 in here in this anonymous function will
  • 00:18:49 not refer to or class but to the button
  • 00:18:53 because essentially we just did the same
  • 00:18:55 with that before before using bind now
  • 00:18:58 when using an anonymous arrow function
  • 00:19:01 which is all the next generation
  • 00:19:03 JavaScript syntax introduced with es6
  • 00:19:05 then this changes now if I save this in
  • 00:19:08 a reload it works
  • 00:19:11 and the reason for that is that arrow
  • 00:19:13 functions specifically solve that
  • 00:19:16 problem of this behaving differently
  • 00:19:19 because often you don't want it to
  • 00:19:21 behave differently and therefore arrow
  • 00:19:23 functions were introduced to basically
  • 00:19:25 keep the context of this or the
  • 00:19:28 reference of this so if you use an arrow
  • 00:19:31 function here this will refer to the
  • 00:19:34 exact same thing it would refer to if it
  • 00:19:36 were used outside of that arrow function
  • 00:19:38 this is the idea behind them and
  • 00:19:40 therefore now this and here refers to
  • 00:19:42 the constructor now we call ad name on
  • 00:19:45 this so on our constructor and therefore
  • 00:19:48 in the function in ad name this refers
  • 00:19:51 to called it who called it well
  • 00:19:53 our constructor so this inside here
  • 00:19:56 still refers to our constructor to our
  • 00:19:58 class a lot of mind yoga here I guess
  • 00:20:02 but really something which helps you a
  • 00:20:04 lot once you wrap your head around and
  • 00:20:06 really something I also encourage you to
  • 00:20:08 just play around with you got the code
  • 00:20:10 you got the finished code to below the
  • 00:20:12 video and I hope that this was helpful
  • 00:20:13 see you in future videos hopefully bye