The “this” keyword of JavaScript causes confusion for people, who start to use Javascript language and mainly for those who start after using the other languages. Here the main question is how to use “this” in the right way in a callback function.
Lets the following example:
function nameofFunction() {
this.data = 'yourDataFromThis';
const data = 'yourData';
setTimeout(function callback() {
console.log(this.data); // undefined
console.log(data); // someData
}, 100);
}
nameofFunction();
This code does not give the required output. Now, what is the problem with this code? Why does the data work as intended, but this. data not?
The problem is that the value of “this” depends on where the work is being done. This is called runtime-binding. The values of variables depend on where the functions are defined.
A common misconception in this example stems from the fact that many people think that “this” has a value that it has when defining callback function. The fact is, it will have a value depending on the context in which the callback function will be called. “this” keyword is special in that sense. It behaves differently as compared to other keywords and “this” keywords also from other languages such as Java.
Method to access “this”:
- The “self” pattern
The most commonly used pattern to create a variable called self and gives you the value of this on the scale where our work is defined:
function nameofFunction() {
this.data ='yourDataFromThis';
const data = 'yourData';
const self = this;
setTimeout(function callback() {
console.log(self.data); // someDataFromThis
console.log(data); // someData
}, 100);
nameofFunction();
By announcing a new variable called “self” (any other valid name variant will work again) and giving it the value of “this”, you get the character you want. - Explicitly setting “this”
Another way to solve our problems is to use “this” explicitly for the function.
function nameofFunction() {
this.data = 'yourDataFromThis';
const data = 'yourData';
const callback = function callback() {
console.log(this.data); // someDataFromThis
console.log(data); // someData
};
setTimeout(callback.bind(this), 100);
}
nameofFunction();
The “bind” actually creates a new function with “this” permanent bond to any value you transfer to the bind. It is a built-in solution to the problem. - Arrow functions
function nameofFunction() {
this.data = 'yourDataFromThis';
const data = 'yourData';
setTimeout(() => {
console.log(this.data); // someDataFromThis
console.log(data); // someData
}, 100);
}
nameofFunction();
Arrow functions do not have a much shorter syntax than unknown function functions. They also face the keyword “this” as they could change. That means “this” will keep the value of the closed lexical context. That doesn’t mean he gets a copy of that amount. It can be modified with other functions like any other variables within the closure.
Which method is best
That depends a lot on the situation. I personally see no reason to use “self”. One has to keep in mind that the application of “this” to JavaScript is not a risk but intended. It can be helpful and flexible. So don’t fight this goal by simply saying “var self = this”; at the beginning of all your works. Try using the keyword “this” as a reference for something that calls for your work.
Using the “bind” and using the arrow functions both have their own operating conditions. The functions of the arrow remain unknown. So if you would like to have a named job, you should use “bind”. If an unknown function is right for you and you want a very short code, you can use the arrow functions. Just know that with arrow functions, you don’t have the freedom to change the binding “this” of the function.
There is no single best solution. In the end, it is a wise decision. Just make sure you know why you select your path.