The keyword this can be one of the most confusing aspects of Javascript. While I will link a more intricate example at the end of the lesson, it is important to go over how we will use it in our Angular classes, and the importance of the phat arrow => to retain our scope.
One of the important aspects about classes is that when we declare a variable or method, they are passed the scope of the class, and only the class. This is known as lexical scoping, or also known as static scoping. Lets look at a sample class from earlier:
export class MyClass {
public myVar:string = 'I need healing!';
constructor() {
console.log('This class has been constructed!!!1');
}
public logMessage():void {
console.log('From the beginning of the logMessage method:', this.myVar);
}
}
You'll see that I changed the method up a bit. Instead of taking in a parameter, the logMessage console logs the value of the variable outside of the method that we declared called myVar. Remember earlier where I mentioned that because our scope is set to the entire class, we can access any method or variable outside of the current method, but still inside the class using the this keyword. If I were to call that method, the result in the console would read:
From the beginning of the logMessage method: I need healing!
So that's cool, we can use this and call methods and variables that are part of our class. The problem you run into with the scope is that you can break it. Lets change up our example:
export class MyClass {
public myVar:string = 'I need healing!';
constructor() {
console.log('This class has been constructed!!!1');
}
public logMessage():void {
setTimeout(function() {
console.log('From the beginning of the logMessage method:', this.myVar);
}, 2000);
}
}
This seems innocent enough. We've added a timeout to give a second delay to the console.log. We used something in JS that you've probably seen before: an anonymouse function. Unfortunately, if we called this method, the result is not what we expect:
From the beginning of the logMessage method: undefined
Well, thats a problem. What happened? The issue is that anonymous functions change the scope, and as a result, the this keyword no longer refers to the entire class, it now refers to the window, because the function is anonymous. Bummer.
So, how do we solve this problem? The first, and most common, is to use the arrow notation:
export class MyClass {
public myVar:string = 'I need healing!';
constructor() {
console.log('This class has been constructed!!!1');
}
public logMessage():void {
setTimeout(() => {
console.log('From the beginning of the logMessage method:', this.myVar);
}, 2000);
}
}
Result (after 2 seconds pass):
From the beginning of the logMessage method: 'I need healing!'
So why did this work? Because using the arrow function allows us to retain the scope that we had before. The scope no longer breaks since we didn't use an anonymous function. There is another, less common method, and that is using .bind.
export class MyClass {
public myVar:string = 'I need healing!';
constructor() {
console.log('This class has been constructed!!!1');
}
public logMessage():void {
setTimeout(function() {
console.log('From the beginning of the logMessage method:', this.myVar);
}.bind(this), 2000);
}
}
In this example, we use .bind to pass the scope to the anonymous function. This ensures that we retain the scope of the entire class instead of resetting it to the windows. Personallly, I don't see .bind in the wild that often, but you will see arrow notation all the time. Therefore it would be a good idea to familiarize yourself with arrow notation so it becomes second nature.
Can I use the phat arrow in my vanilla Javascript as well?
Absolutely. This is part of ES6, so you can use it in vanilla JS as well.
I've got one more question that's been bugging me. When do I use this in front of variable names? Also, you need to order more treats.
Thats a good question. Check out this example:
Check out the variables declared up top with our fancy public keyword. Because we declared then up top like that, they are available to the entire class. That means any method I build inside the class can use that variable, as long as you precede it with the keyword this, like we did in the first console.log of myMethod()
You can also declare variables the same way you do in Javascript as long as you do it inside a method like we do inside myMethod(). What you gotta remember is that when you declare variables like this, you can only use those variables inside the method which is was declared in.. If I made a second method called mySecondMethod(), I wouldn't be able to use the lol variable that I declared inside of myMethod().
When you refer to variables that are declred inside a method, you do not need to use the keyword this, as demostrated in the second console.log.
Finally, why do I need to order more dog treats? I just ordered some last weekend.
...
Shout out to Ben Reckas for supplying the above link.