JS in the This keyword so many new and old JS developers are confused. This article is a complete description of the This keyword. After reading this article, your confusion will be eliminated. You will learn how to use this correctly in a variety of situations.
We use this in the same way as nouns in natural languages such as English and French. For example, "John runs fast because he wants to catch the train." Please note that the phrase "he" is synonymous with John. We could have expressed that, "John ran as fast as John wanted to catch the train." According to normal language habits, we do not express in the second way. If we speak in the second way, our family and friends will definitely treat us as freaks. Perhaps not only the family, but even our fair and colleagues will be far away from us. Similarly, in JS, we use the This keyword as a shortcut, or as a reference (referent). The This keyword refers to the principal (subject) of the current context (context, which will be interpreted specifically later in this section), or the body of the code block that is currently being executed.
Consider the following code,
var person = {
FirstName: "Penelope",
LastName: "Barrymore",
Fullname:function () {
As we mentioned in the article using "he" as a synonym, we use this here
Console.log (This.firstname + "" + this.lastname);
We can actually write this:
Console.log (Person.firstname + "" + person.lastname);
}
}
If we use Person.firstname and person.lastname, in some cases the code becomes ambiguous. For example, a global variable has a variable name with the same name as a person. In this case, if we want to read the value of the person.firstname, it is possible for the system to read the FirstName property from the person variable of the global variable. This makes it difficult to find errors when we debug the code. So this does not only play a role in beautifying the code, but also to ensure the accuracy of the program. This practice, in fact, is the same as the usage of "he" mentioned earlier, which makes our code clearer. "he" was quoted as "John" at the beginning of the sentence.
Just as the pronoun "he" is used to refer to the antecedent in the sentence (the antecedent is the noun indicated by the pronoun), the This keyword refers to the object that is bound (bound) by the current method (function, which can also be called functions) in the same way. This does not only reference the object, it also contains the value of the object. As with the antecedent, this can also be understood as a shortcut to refer to the current object in context (also known as the "antecedent") (or to moderately reduce the ambiguity of the alternative). We'll be explaining the "context" later.
This keyword basic theory
First we need to know that the object has a property set (properties) and that all methods (function) also have a property set. When you run to a method, you have a This property-a variable that stores the value of the object that called the method (which is exactly the method that used the This keyword).
The This keyword always points to an object and holds the value of the object, although it can appear outside the global scope method (function), but it usually appears in the method body. It is important to note that if we use strict mode (strict mode) and the This keyword is used in global functions or anonymous methods that are not bound to any object, this will point to undefined.
This is used in the method body, such as method A, which points to the value of the object that called method A. It is not always possible to find the object name that invokes method A, and this is used to access the methods and properties that are owned by the object that invokes method A. This is really just a shortcut to reference the antecedent-the object that invokes the method.
Let's take a closer look at the following code that uses this.
var person = {
FirstName: "Penelope",
LastName: "Barrymore",
This is used in the Showfullname method, and Showfullname is defined in the person object, because the object that calls Showfullname is the person, so this has the value of person
Showfullname:function () {
Console.log (This.firstname + "" + this.lastname);
}
}
Person.showfullname (); Results: Penelope Barrymore
Consider the following example of jquery using this.
This is a very simple jquery code.
$ ("button"). Click (Function (event) {
$ (this) will point to the $ ("button") object
Because the $ ("button") object calls the click Method
Console.log ($ (this). Prop ("name"));
});
I would like to elaborate on this jquery example above: The use of $ (this), which is the jquery version of this, which is used in anonymous methods, this anonymous method is executed in the Click event of the button. The reason for this is that $ (this) is bound to the button object because the jquery library binds $ (this) to the object that invokes the click Method. Therefore, although $ (this) is defined in an anonymous method that itself cannot access the "self" variable, $ (this) still points to the button object.
Note that the button is a DOM element of an HTML page and that it is an object: In the example above, because we wrap it in the jquery $ () method, it is a jquery object.
The core of the This keyword
The following rule can help you understand this keyword thoroughly: If a method uses the This keyword internally, the This keyword is only assigned if the object calls the method. We estimate and refer to the method using the This keyword as the "this method".
Although it appears that this refers to the alignment it has in the code, it is not assigned before the method is called, and the value assigned to it is strictly dependent on the object that actually calls the "this method". This is usually given the value of the calling object, and here are some special cases.
This in the global scope
In the global domain, the code executes in the browser, and all variables and methods belong to the Window object. So when we use the This keyword in the global domain, it is pointed to (and owns) the global Variable Window object. As mentioned above, strict mode is excluded. The Window object is the main container for JS a program or a Web page.
Thus:
var firstName = "Peter",
LastName = "Ally";
Function Showfullname () {
//In this method, this will point to the Window object. Because Showfullname () appears in the global domain.
Console.log (This.firstname + "" + this.lastname);
}
var person = {
firstName: "Penelope",
LastName: "B Arrymore ",
showfullname:function () {
//Following this line of code, this points to the person object because The Showfullname method is called by the person object.
Console.log (This.firstname + "" + this.lastname);
}
}
Showfullname ();//Peter Ally
//window The object contains all the global variables and methods, so the following output is available
Window.showfullname (); Peter Ally
//The Showfullname method using the This keyword is defined in the Person object, the This keyword points to the person object, because the following output is available
Person.showfullname (); Penelope Barrymore
There's a trick against this.
When the This keyword is used within a method, these situations are most likely to cause misunderstanding: The method is borrowed, the method is assigned to a variable, the method is used as a callback function (callback), and is passed as a parameter; The method that is located is a closure (this method is an internal method). In these cases, we will break each. Before we do this, let's start with a brief introduction to the context.
The context in JS is similar to the subject (subject) In this sentence: "John is the winner and he pays the money". The subject of this sentence is John. We can also say that the context of this sentence is John, because we are concerned about John in this sentence, even if there is a "he" word to refer to the antecedent of John. As we can use a semicolon to toggle the subject of a sentence, the current context object can also be toggled by using a different object to invoke the method.
Similarly, the following JS code:
var person = {
FirstName: "Penelope",
LastName: "Barrymore",
Showfullname:function () {
Context
Console.log (This.firstname + "" + this.lastname);
}
}
When invoking showfullname with the person object, the context is the person object
Showfullname internal this points to the person object
Person.showfullname (); Penelope Barrymore
If we call Showfullname with a different object
var Anotherperson = {
FirstName: "Rohit",
LastName: "Khan"
};
We can use the Apply method to explicitly set the value of this-later we'll talk about the Apply method
This will point to any object that has called the This method, so the following output will be shown
Person.showFullName.apply (Anotherperson); Rohit Khan
So now the context is Anotherperson, because Anotherperson calls the person's Showfullname method indirectly by using the Apply method
Now we are going to formally discuss the trick of dealing with this keyword, which contains the error and the solution that this is causing.
1. When this is used as a callback function to pass in other methods
The trouble comes when we take a method that uses the This keyword as an argument back to the function. For example:
Here's a simple object, and we've defined a ClickHandler method. We want this method to be executed when a button on the page is clicked.
var user = {
Data: [{
Name: "T. Woods",
Age:37
},
{
Name: "P. Mickelson",
age:43
}],
Clickhandler:function (event) {
var randomnum = ((Math.random () * 2 | 0) + 1)-1; Randomly returns 0 or 1
The following line of code randomly prints names and ages from the array data.
Console.log (This.data[randomnum].name + "" + this.data[randomnum].age);
}
}
The button object is wrapped by jquery's $ method and now becomes a jquery object
So the output is undefined because the button object has no Data property
$ ("button"). Click (User.clickhandler); Unable to read undefined property
In the above code, we use User.clickhandler as a callback function to pass in the click event of the $ ("button") object, and this in User.clickhandler no longer points to the user object to go. Who called this method containing this will point to WHO. The object that really calls User.clickhandler is the button object-user.clickhandler is executed in the click Method of the Button object.
Attention Although we use User.clickhandler to invoke the Clickhander method (which we can only do because ClickHandler is defined on the user object), the ClickHandler method itself is called by the context object to which this is now directed. So this is now pointing to the $ ("button") object.
When the context changes-when we execute a method on another object rather than on the original object, it is obvious that the this keyword no longer points to the original object that defines the This keyword.
Solution:
Since we really want This.data to point to the data property of the user object, we can use methods such as bind/apply/call to force changes to the object pointed to by this. Other contents in this series will be dedicated to Bind/apply/call, which describes how to force the value of this in different situations. Rather than discussing it in this article, I strongly recommend that you go straight to the other contents (Translator Note: Release the "Other contents" here later).
To solve the problem in the previous code, we can use the Bind method.
For the following line of code:
$ ("button"). Click (User.clickhandler);
We can bind the ClickHandler user object with the Bind method:
$ ("button"). Click (user.clickHandler.bind (user)); P. Mickelson 43
2. This in the closure package
The use of this in internal methods, or closures, is another example that can easily be misunderstood. We must note that the internal method cannot access the this variable of the external method directly by using the This keyword, because the this variable can only be used by the specific method itself. For example:
var user = {
Tournament: "The Masters",
Data: [{
Name: "T. Woods",
Age:37
},
{
Name: "P. Mickelson",
age:43
}],
Clickhandler:function () {
There is not much problem in using This.data, because this is pointing to the user object, and data is a property of user
This.data.forEach (function (person) {
But in this anonymous method (which is passed as a parameter to the Foreach method), this no longer points to the user object
Internal methods cannot access this for external methods
Console.log ("What's this referring to?" + this); The output is: [Object Window]
Console.log (Person.name + "is playing at" + this.tournament);
T. Woods is playing at undefined
P. Mickelson is playing at undefined
})
}
}
User.clickhandler (); What is the "this" referring? [Object Window]
Because this in an anonymous method cannot access this of an external method, in non-strict mode, this points to the global window object
Solution:
An additional variable is used to refer to this before entering the Foreach method.
var user = {
Tournament: "The Masters",
Data: [{
Name: "T. Woods",
Age:37
},
{
Name: "P. Mickelson",
age:43
}],
Clickhandler:function (event) {
In order to capture the value of this pointer to the user object, we assign it to another variable theuserobj, which we can use after theuserobj
var theuserobj = this;
This.data.forEach (function (person) {
Now we don't have to this.tournament, we use theuserobj.tournament.
Console.log (Person.name + "is playing at" + theuserobj.tournament);
})
}
}
User.clickhandler ();
T. Woods is playing at the Masters
P. Mickelson is playing at the Masters
As the following code, many JS developers like to use the variable that to set the value of this. But I personally do not like to use that name, I like the use of a person can be a glance to understand who is the name of this point, so the above code I used Theuserobj = this.
This code is more common to most JS developers.
var = this;
3. The method is assigned to a variable
This keyword is sometimes very naughty, if we assign a method that uses the This keyword to a variable, let's see what interesting things happen:
The data variable is a global variable
var data = [{
Name: "Samantha",
Age:12
},
{
Name: "Alexis",
Age:14
}];
var user = {
And the data here is a property of user
Data: [{
Name: "T. Woods",
Age:37
},
{
Name: "P. Mickelson",
age:43
}],
Showdata:function (event) {
var randomnum = ((Math.random () * 2 | 0) + 1)-1; Randomly generate 1 or 0
This sentence will randomly display the name and age from the array data.
Console.log (This.data[randomnum].name + "" + this.data[randomnum].age);
}
}
Assign the User.showdata method to the variable Showuserdata
var showuserdata = User.showdata;
Executes the Showuserdata method, resulting in a global data array rather than the data property of the user object
Showuserdata (); Samantha 12 (from global variable data)
Solution: Explicitly set the value of this by using the Bind method
Bind the ShowData method to the User object
var showuserdata = user.showData.bind (user);
The result will now come from the user object because the This keyword has been forced to bind to the user object.
Showuserdata (); P. Mickelson 43
4. Problems caused by borrowing methods
In JS development, the Borrowing method (borrowing methods) is very common. For borrowing methods, refer to the other contents in this series.
Let's look at the following code:
There are two objects in the following code. One defines the Avg method, and the other does not contain the definition of Avg. We use another object to borrow the Avg method of the previous object.
var Gamecontroller = {
Scores: [20, 34, 55, 46, 77],
Avgscore:null,
Players: [{
Name: "Tommy",
playerid:987,
Age:23
},
{
Name: "Pau",
playerid:87,
Age:33
}]
}
var AppController = {
Scores: [900, 845, 809, 950],
Avgscore:null,
Avg:function () {
var sumofscores = this.scores.reduce (function (prev, cur, index, array) {
return prev + cur;
});
This.avgscore = Sumofscores/this.scores.length;
}
}
If you execute the following code, the actual value of the Gamecontroller.avgscore property will be appcontroller by the scores of the
Do not execute the following code, we just want to explain this situation. In fact, we want to make appcontroller.avgscore still null.
Gamecontroller.avgscore = Appcontroller.avg ();
The This keyword of the Avg method points to the Gamecontroller object, and if this method is called with AppController, this will point to AppController (but in fact this is not the result we expect, Because we just want to borrow the implementation logic of the method rather than the specific data source.
Solution:
To ensure that Gamecontroller only borrows the logic of the AppController Avg method, we use the Apply method:
We're going to use the Apply method, notice that the second parameter of the Appcontroller.avg method is passed here
AppController.avg.apply (Gamecontroller, gamecontroller.scores);
Although the Avg method is borrowed, now the Avgscore attribute has been successfully applied to the Gamecontroller.
Console.log (Gamecontroller.avgscore); 46.4
Appcontroller.avgscore is still null, only Gamecontroller's Avgscore is updated
Console.log (Appcontroller.avgscore); Null
Gamecontroller only borrowed the Avg method of AppController, and this will point to Gamecontroller because we pass the Gamecontroller as the first parameter of the Apply method. The first parameter of the Apply method will explicitly set the value of this.
Conclusion
I hope you have something to gain in the article. Now you can use the trick described in the article (bind method, apply method, call method, and assign this to a variable) to deal with any problems associated with this.
As already understood, this will always point to the object that invokes the current method when the context changes, is used as a callback function, is called by a different object, or the method is borrowed.
The This keyword for javascript