[JavaScript] The Secret of the setTimeout - this
How does "this" work in setTimeout?
Before we start to talk about the topic. Let's start a simple example to recall "this". For example, to get cx60
, we will call the car.printModel()
. Pretty straightforward.
const car = {
model: 'cx60',
printModel() {
// 'this' refer to the car object
console.log(this.model);
}
}
car.printModel(); // "cx60"
Next, how to get cx60 after 1000 ms? It is not difficult, just execute the car.printModel()
inside of the setTimeout
like this setTimeout(car.printModel, 1000)
. Wait, what result will we get? undefined
rather than cx60
.
But, Why ????
Because of this
, this
keyword usually makes confusing when learning JS ๐ฅฒ. If put car.printModel
inside of the setTimeout
like this example, setTimeout(car.printModel, 1000)
, it would consider it scope is window
.
Before we fix it, I want to show you one example to make it clear why this situation happened. For the following example, declared a parameter c
and assign car.printModel
rather than call it. Now, its scope will refer to the window
. We will get undefined
rather than cx60
.
// this scope is window
const c = car.printModel;
c(); // undefined
How could we fix it ? Use a wrapper function or bind()
// wrapper function
const anrrowWrapperC = () => { car.printModel() }; // arrow function
anrrowWrapperC() // "cx60"
const declaredWrapperC = function { car.printModel() }; // normal declared function
declaredWrapperC() // "cx60"
const c = car.printModel;
const bindC = c.bind(car);
bindC(); // "cx60"
If we take a close look when use wrapper function. We will find car.printModel()
still executed by itself when call wrapperC
, rather than assign to other declare parameter to execute (such as c
in the previous example). Using the wrapper function here, just like take out of wrapper function to execute car.printModel()
, so its this
keyword still refer to car
object. There is a little bit difficult to understand why no different when using arrow function and normal declared function will get the same result. I think This is the reason why arrow function and normal declared function will not affect this here of its scope. (Probably is easy for you, but I spent a few time trying to understand ๐ค)
I didn't give much explanation here when use bind because I think it is intuition solution.
Solution & Conclusion
If you read carefully before, you definitely know the solution to setTimeout(car.printModel, 1000)
. Yes, use a wrapper function or bind(). ๐
// Solution 1: Wrapper function
setTimeout(function() { // normal declared function
car.printModel();
}, 1000) // "cx60"
setTimeout(() => { // arrow function
car.printModel();
}, 1000) // "cx60"
// Solution 2: Use bind function
setTimeout(car.printModel.bind(car), 1000); // "cx60"
Thanks for the reading. Welcome to leave the comments to discuss further. ๐ค
Reference
Subscribe to my newsletter
Read articles from CC directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by