If you already have a subscription, you can sign in.
Enjoy free content straight from your inbox 💌
00:00
A common source of bugs in JavaScript is how this is handled. It can be simplified quite easily if you remember that this is the devil, sorry, calling context. I meant to say this is the calling context to demonstrate the calling context. Nature of this consider a simple function that takes a value as a parameter and in addition to logging the value, it also logs whatever is contained by the this keyword to the console. If we invoke the function by itself in modern JavaScript, there's not going to be any special list that gets passed in and in fact it'll point to the value that we've looked at a few times, which is undefined.
00:36
Let's look at one way how we can pass the value in for this context. If we wanted to consider a simple DWS script object with the name property containing the string, John, just like we can specify what the parameter will be for a function when we invoke it, we can actually also specify what the this context will be by invoking the function using a special method that exists on all functions, which is call here we are saying that invoke the simple function, use the personal object as the value for this and use 4, 5, 6 as the argument, which of course is going to get assigned to the parameter value.
01:10
In addition to how we can explicitly passing at this value, this can get implicitly automatically passed in as well depending upon how the function is invoked. To demonstrate that, let's add a property to the person object called simple, which points to the simple function. Now if we invoke simple on the person object, whatever exists before the.is what gets passed by JavaScript as the value for this since here we have person do simple person is the value that gets passed for this to the simple function and that is of course what we see within the logs and the program output.
01:45
The passing of this based on the object that the function is in worked on is the main usage of this and it is fundamental to how modern JavaScript classes work. We've looked at JavaScript classes and how they used this keyword, but let's take a fresh look to add some additional depth to the meaning of this. In classes, consider a simple class called point that takes in its constructor the values of X and Y. When the class constructor gets invoked by JavaScript, it actually creates a new object for that class and then passes it in using the this keyword and all that we are really doing within this constructor is
02:21
adding some stuff to this object and this is the same object that gets passed back to us within our methods so we can use it to access its values. For example, here we are reading this tox and this dot y. When we create new instance of the class, we do that with the new operator and this is the thing that triggers JavaScript to create a new object and pass that into the constructor. Additionally, the constructor has an implicit return of this value back to the calling point, which of course is why we see that point is that object that we mutated to have X of one and Y of two and just like any other JavaScript object,
02:57
we can access these values using The dot rotation. The real interesting thing to note over here is that when we invoke the log method on the point object, the value of this is actually getting passed simply because of the fact that we do point dot before we invoke the log method. This means that methods within JavaScript are actually quite lightweight and they can actually even be shared by all of the instances of the class because the correct instance will get passed in when we invoke the method on that instance, this is most commonly used in classes, but now that we understand that it is just a calling context that gets passed
03:33
in. We can use this fact to create utility functions that can be attached to any object. Consider a simple grow older function that simply increments the age property of whatever will get passed in. As this, we can take the grow older function and attach it as a member of any JavaScript object that we want and that will actually automatically ensure that when the function gets invoked that object will get passed in as the calling context Here, we've provided the grow older method as a property of Jane as well as a property of John, so as an example, if he invoke it on Jane who is currently 32,
04:08
the age will get implemented by one and now when we read Jane age we should see 33 and the same should be true for John as well. When we invoke grow older on John, John will automatically get passed in as this and John's age will get implemented from 21 to 22. And now if you run this code indeed that is exactly what happens. We see the updated ages of 33 and 22, the Tao skip. This will always be the calling context except for two scenarios. The first scenario is when we explicitly bind the value of this by using the
04:43
function bind method, consider a simple log name function that logs the value of the name property of whatever this gets passed in. Here we are using optional chaining to look up the name property so if this is undefined then the whole chain will resolve to undefined. If we invoke log name by itself, of course there will be no this, which means that undefined is what will get logged to the console. If we create two objects with the log name method, one with the name chain and one with the name John, when we invoke Jane dot log name, then Jane is what gets passed in and that is what we will see on the console and the same will be true for John as well.
05:17
John will get passed in and we will see the log. John, we can actually create a standalone version of the function that always passes in a particular value for this by using the functions built-in bind method here. Log name Jane is a modified copy of the original log function such that whenever we invoke log name Jane, the value of this will always be Jane. Now this is a copy of the original function. The original function is still completely the same as it was. It'll happily log the value of undefined since log name Jane is bound to Jane. It'll always use Jane as the calling context,
05:52
so even if you try to attach it to a different object with the name Jack and try To invoke it on the JAK object, it's not going to matter. Jane is what's going to get passed in and that is what we will see on the console beyond the bind method. The other scenario in which this is not the calling context is arrow functions. Arrow functions capture this from the Lal context, which is just a fancy term for the surrounding scope. Consider a simple auth class that has remember is logged in which we initialize to false and then we have utility methods login which set it to true and log out which set it to false.
06:27
If we create an instance of auth and then we invoke the login method, the author object will get passed into login and auth.is logged in, we'll get set to true. And of course if we do author logout, then again authors what gets passed in and author is logged in is what gets set to false. If however we manage to invoke these functions without using author dot for example, we store a reference to the login method into its own variable and invoke it that way, then this author object is not the thing that will get passed in as this undefined is what will get passed in as this and it'll cause a runtime error and you might think that, hey of course this is never going to happen on me,
07:04
I'm always going to do author login, but as we've seen before, this implicit assignment of a method to a variable is exactly what happens when an argument gets assigned to a parameter. So if we decide that we want to log out after one second using set timeout, set timeout is not actually going to invoke author logout, it's simply going to invoke the logout function by itself just like we were invoking the login function by itself. And of course this is also going to result in a runtime error and this is where the error functions come in. We can actually replace our methods with instances of error functions and error
07:39
functions automatically capture the value of this from the surrounding scope. So in this particular case they will capture the instance of the auth class, which means that this no longer depends upon the calling context and it'll always point to the oath instance with this simple change in place, it doesn't matter how we invoke the login method or how we invoke the logout method. So our independent call for login will also work. We should see is logged into true and similarly our call to logout made by set timeout will also work. So if you set another timeout for two seconds and logout auth is logged in,
08:14
we should see false and indeed when we run this code that is exactly what we see. There is a slight performance difference in using a method versus using an arrow function as an instance property. The method is shared by all the instances, which means of course that it needs to be called correctly so that it gets the correct instance whereas an error function captures this correctly and is not shared between the different classes. However, the performance difference in modern JavaScript is pretty negligible. In addition to using error functions when declaring class methods, we can also use error functions when creating callbacks inside these methods to
08:49
ensure that this is preserved. Let's expand our simple auth class that manages And is logged in bullion with a new method called logout Soon. This method first checks if the user is logged in and if they are sets a time out to log the message logging out and then invokes this logout. Let's test it out by invoking au logout soon and then set a time out for two seconds. That is one second after the logout should have happened to log out, the author is logged in value. If you run this code, we should see the author is logged in value of true,
09:24
then we should see the message logging out and then we should see author is logged in value of false. The observant among you might already know that this particular piece of code is not going to work and no surprise it does not work. It fails to call this drug log out because as you might have guessed, this is going to be undefined. The function that is being invoked by set timeout has no magical knowledge about this context, but notice that this is available just one line before so we can actually use our magical error function once more to capture the value of this from the surrounding context and that will ensure that this within the set
10:01
timeout is going to point to the this within the logout soon method and therefore this dot logout is going to work just like this is logged in is going to work. And now if you run this code, it executes without any issues. We see the logged in true, we see the logging out message and then because this logout was successfully called the logged in value turns to false. A common use case for this is to create classes which offer what is called a fluent a P i A few built-in JavaScript APIs do this and we can achieve the same effect ourselves quite easily by simply returning this from our methods.
10:37
Consider a simple calculator class that starts off with an initial value which we store within the value property of the object that gets assigned to us. With this, we create a method add that accepts the number and and then adds the value with that number, but then we do something interesting. We return the value of this from the ad function. It makes the object that we are dealing with immediately available as the response for the ad method. We can create other fluent methods on our calculator class as well. For example, here we are creating subtract that simply subtracts from the value and then again returns this. Let's demonstrate the fluent usage of this A P I.
11:14
By calculating the result of a one plus three minus two, we simply create an instance of the calculator passing in the value of a one. Then we invoke add with the number three, then subtract with the number two, and then read the final value as the result. Because the new operator automatically returns this, we can chain off of that to invoke add and within add we are explicitly returning this, which means that we can chain off of that to invoke, subtract. And finally, from subtract we also return this, which means that we can chain off of that to read the final value.
11:49
And of course, if you run this code, no surprises, it calculates the correct result. The result of one plus three minus two is going to be two. I hope you enjoyed this tutorial. As always, thank you for joining me and I will see you in the next one.