Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
This knowledge point is often involved in the interview questions, this must understand!!
This is a concept that many people will confuse, but in fact it is not difficult at all, but many articles on the Internet have complicated simple things. In this article, you will surely understand the concept of “this” thoroughly.
Let’s start with a few function call scenarios
function foo() {
console.log(this.a)
}
var a = 1;
foo();
const obj = {
a: 2.foo: foo
}
obj.foo()
const c = new foo()
Copy the code
Let’s look at each of these scenarios one by one
- For direct calls
foo
Say, no matterfoo
Where does the function go,this
It must bewindow
- for
obj.foo()
So, we just have to remember, whoever called the function isthis
So in this scenariofoo
The function this isobj
object - for
new
In the manner of,this
It’s bound to foreverc
Above, it will not be changed in any waythis
Now, having said that, there’s no problem with this in a lot of code, so let’s look at this in the arrow function, okay
function a() {
return () = > {
return () = > {
console.log(this)}}}console.log(a()()())
Copy the code
First, the arrow function doesn’t actually have this. The “this” in the arrow function depends only on the “this” of the first normal function that wraps the arrow function. In this case, because the first normal function that wraps the arrow function is a, this is the window. In addition, using functions such as bind for arrow functions does not work.
The last case is the context-changing API called bind. For these functions, this depends on the first argument, or if the first argument is empty, the window.
So speaking of bind, have you ever thought about what the context would be if you bind a function multiple times?
let a = {}
let fn = function () {
console.log(this)
}
fn.bind().bind(a)() / / = >?
Copy the code
If you think the output is a, you are wrong. We can actually convert the above code to a different form
/ / fn. The bind (). The bind is equal to (a)
let fn2 = function fn1() {
return function() {
return fn.apply()
}.apply(a) }
fn2()
Copy the code
As you can see from the above code, no matter how many times we give bind, this in fn is always determined by the first bind, so the result is always window.
let a = { name: 'yck' }
function foo() {
console.log(this.name)
}
foo.bind(a)() // => 'yck'
Copy the code
That’s the rule for this, but it’s possible to have multiple rules at the same time, and the different rules will decide where this ends up depending on which rule has the highest priority.
First, the new method takes precedence, followed by the bind method, followed by the obj.foo() method, and finally the foo method. Meanwhile, the arrow function’s this, once bound, cannot be changed by any method.
If you’re still feeling a little convoluted, take a look at the flow diagram below, which is for a single rule.