How to make this point clear?

I have to say that we need a premise to figure out this.

You first need to know the basic concepts of function, object, scope and so on.

It would be great to know the call, apply and bind methods

Of course, it is very important to learn Chinese well

You need to know the difference between first person and second person and third person

Let's take a look at the news:

"The devil in my body has been locked for so many years, and now the chain has been loosened."
"I'm scared, lonely and confused. I'm going to fight back against the society, the root of my pain. I want to hurt the society as much as I can and then die."

This chilling passage was written by Joseph Duncan, a suspect in a series of homicides in North Dakota, on May 11, 2005. When people saw this text nearly two months later, he had brutally killed three people in a family of five and kidnapped two other children aged 8 and 9 respectively.

Suppose you are a policeman and catch a suspect
Then you searched the diary in his home. How do you feel now?

You must think that if the suspect wrote it himself, wouldn't it be tantamount to pleading guilty?

Of course, the suspect can also quibble that this diary was not written by me at all, it was just a passage I excerpted from the Internet

Let's try to change the diary a little to see what effect it will have.

The demon in his body has been locked for so many years, and now the chain is loose. He was afraid, lonely and confused. He was going to fight back against the society, the root of his pain. He wanted to hurt the society as much as he could and then die.

Did you notice?

Changed the first person to the third person

It doesn't look like a diary at all. It's more like a novel story.

Why is there such a big difference in the change of a word?

With thinking about this problem, let's start today's study of this point.

English meaning of this

Look at the English explanation first. This: so, this

Next, let's look at a piece of code

var obj = {
    show : function(){
        console.log(this);
    }
}
obj.show();

The results are easy to predict and print the obj object itself

In JS, this belongs to a keyword, which can be understood as a system built-in command

Usually, we interpret its meaning as: current object

So the question comes: who is the current object?

In the above code case, this represents the object obj

Let's look at the next piece of code

function show(){
    console.log(this);
}
show();

Result print window object

If you are surprised by the print result, you may have overlooked a common sense problem

window object can be omitted without writing!

Therefore, the above code is actually equivalent to:

function show(){
    console.log(this);
}
window.show();

Let me give another common example about event binding

btn.onclick = function(){
    console.log(this);
}
btn.onclick();   //Call function manually

//In addition to manual calling, clicking a button with the mouse can also trigger function execution

Finally, whether it is called manually or by clicking a button
The print results are btn objects

We seem to have summed up a law that this points to

this always points to the object that calls the function

If your code structure is like this

Object Function ();
Then, this in the function must point to the object itself!

Assuming this conclusion is true, we might as well test our conjecture!!

function show(){
    console.log(this);
}
window.show();  //Print window objects

var obj1 = {};
obj1.show1 = show;
obj1.show1();  //Print obj1 objects

var obj2 = {};
obj2.show2 = obj1.show1;
obj2.show2();  //Print obj2 objects

From the example of the above code, you can see that

window object, obj1 object and obj2 object share a function show

window.show == obj1.show1;  //true
window.show == obj2.show2;  //true

Three objects, using the same function

But the printed this is different

window.show(); Print out window objects

obj1.show1(); Print out obj1 object

obj2.show2(); Print out obj2 objects

This seems to confirm our conjecture again:

this refers to the object from which the function is called

Science is rigorous. We still have to verify it again and again before we draw a conclusion
Take another example:

btn.onclick = function(){
    setTimeout(function(){
        console.log(this);
    },0)
}
btn.onclick();

In fact, I just added a delayer based on the original code and set the time to 0

Will the printed this change??

You can think about it first

Usually, according to our intuition, we will think that the delayer only delays the execution time, and the print result is still a btn object,
No change

However, after testing, it is found that the actual print result is the window object

Is our guess wrong?

To explain this phenomenon, we have to look at this code again

btn.onclick = function(){  //< --- this function is represented by A
    setTimeout(function(){ //< --- this function is represented by B
        console.log(this);
    },0)
}
btn.onclick();

Notice that there are two functions in the code. We call them function A and function B respectively

According to our guess just now: this points to which object the function is called from

Therefore, this point will depend on the function it is in

And this function, is it function A or function B?

In fact, you can easily see from the code that this is obviously in function B

Therefore, the results did not print out btn, and now we are not surprised

Because this is no longer inside function A, but inside function B

You may also ask, why does this in function B point to window?

This is actually a special case. We don't know which object calls the function passed in to the timer

In this case, this points to window

Just remember this rule for a while. When you finish learning the scope chain, you will understand its essence

Back to the news we started with

Suppose the diary was written by the suspect. But the diary is full of third person. It's hard to say who he is

Conversely, if the diary is written in the first person. Then "I" must mean the suspect himself

this keyword in JS function is equivalent to the first person pronoun I in our speech

For example:

A said to B, "I'll kill you!"

Here, "I" refers to A and "you" refers to B

B said to A, "I'll kill you!"

Here, "I" refers to B and "you" refers to A

So you see, the same word can refer to anyone. The key depends on who says it

function fn(){
    //this is equivalent to me in Chinese
    //Don't come up and ask who this will point to
    //We must find out the context. Who called fn? (equivalent to who said this sentence from)
    //If we can't figure out this problem, it's meaningless to discuss this point
    console.log(this);
}

So far, we can almost draw a conclusion

Let's finally verify it with a few exercises

var obj = {
    show: function(){
        console.log(this);
    }
}

The above code finally prints the obj object
No matter how many twists and turns, we can only see one conclusion in the end, that is:

Which object calls the function where this is located?

I further modified the code

function fn(){
    console.log(this);
}

var obj = {
    show: fn
}

btn.onclick = function(){
    window.setTimeout(function(){
        obj.show();
    }, 100);
}

In the above code, the final print is obj object

Of course, there will always be some exceptions, such as the following:

function m1(){
    function m2(){
        console.log(this);
    }
    m2();
}
m1();

We can't help asking, which object is the function m2 called by?

We tried everything possible and finally found that it was all wrong.

We never know which object this m2 is called by, as if it were executed like that

What about the actual print results?

No accident, it's still a window object

Final conclusion

1. The direction of all this keywords can only be determined when the function is running

2. The function where this is located is called by which object, and this will point to who

3. When there is no explicit calling object when the function is executed, this points to window

Problems derived from this

A problem has just been left unsolved

btn.onclick = function(){
    setTimeout(function(){
        console.log(this);
    },0)
}
btn.onclick();

We expect this to point to btn, but this now points to window

How to fix this problem? There are many ways

If you don't know call, apply and bind, I'm afraid you can only understand method A

//Method A
btn.onclick = function(){
    var self = this; //Use the variable to save this. The value of the self variable will not change with the environment
    setTimeout(function(){
        console.log(self);  
    },0)
}
btn.onclick();
//Method B
btn.onclick = function(){
    var self = this; //Save this with variable
 
    function fn(){  //Write the code in a function fn
        console.log(this);
    }

    setTimeout(function(){
        fn.call(self); //Forcibly specify this as a self object
    },0)
}
btn.onclick();
/*
  call Method is used to call a function and specify who this can represent
  For example FN call(obj)
  This means that the function fn is called and this points to the obj object
*/
//Method C
btn.onclick = function(){
    var self = this; //Save this with variable
 
    function fn(){  //Write the code in a function fn
        console.log(this);
    }

    setTimeout(function(){
        fn.apply(self); //Use the apply method to call the function and forcibly specify this as the self object
    },0)
}
btn.onclick();
/*
  apply Method is used to call a function and specify who this can represent
  For example FN apply(obj)
  This means that the function fn is called and this points to the obj object
*/
//Method D
btn.onclick = function(){
    setTimeout(function(){
        console.log(this);
    }.bind(this), 0 )
    //Use the bind method to forcibly bind this of the timer function to this of the event function
}
btn.onclick();
/*
  bind Method is used to bind this of the function and return the bound new function at the same time
  for example 
  var fb = fn.bind(obj);
  window.fb();
  No matter who calls fb function, this of the function will point to obj
*/

For the next content, please come back after learning the arrow function of ES6

1. How to judge this of arrow function?
Because the arrow function does not have its own this, it is very simple to pretend that it does not exist, like this:

Now the direction of this is very clear

2. Can the arrow function use call to change the direction of this?

No!! Trying to change this of the arrow function is futile.

The last special case: constructor

  1. What is a constructor?
    Suppose there is a function Fn, we can call it in two ways
    Ordinary call Fn()
    Call new Fn() with the new keyword
    In the second way, the function becomes a constructor

Note that in the constructor, the conclusion we mentioned above is not tenable!!

  1. Who is this in the constructor?
    Please look forward to the next article "constructors and class es"

Tags: Javascript Front-end bind

Posted by nfr on Tue, 24 May 2022 02:27:00 +0300