Proficient in JavaScript's this keyword _ javascript skills

Source: Internet
Author: User
This article mainly introduces the this keyword of JavaScript, which helps you master this keyword. interested colleagues can refer to this keyword in JS to confuse many new and old JS developers. This article will fully elaborate on this keyword. After reading this article, all your puzzles will be eliminated. You will learn how to use this correctly in various situations.

We use this in the same way as natural languages like English and French. For example, "John is running fast because he wants to catch up with the train ". Note that John is synonymous with him in this sentence ". We could have said, "John is running fast because John wants to catch up with the train ". According to the normal language habits, we do not express it in the second way. If we talk in the second way, our family and friends will treat us as geeks. Even our friends and colleagues may stay away from us. Similarly, in JS, we treat the this keyword as a shortcut, or a reference (referent ). This keyword points to the subject of the current context (which will be specifically explained below) or the subject of the code block being executed.

Consider the following code:

Var person = {firstName: "Penelope", lastName: "Barrymore", fullName: function () {// As we mentioned in this article, here we use this console. log (this. firstName + "" + this. lastName); // you can write it as follows: console. log (person. firstName + "" + person. lastName );}}

If we use person. firstName and person. lastName, the Code may be ambiguous in some cases. For example, a global variable has a variable name with the same name as person. In this case, if we want to read the value of person. firstName, the system may read the firstName attribute (property) from the person variable of the global variable ). In this way, it is difficult to find errors when debugging code. Therefore, this is not only used to beautify the code, but also to ensure the accuracy of the program. This method is actually the same as the previous "he" usage, making our code clearer. He references John at the beginning of the sentence ".

Just as the synonym "he" is used to represent the first line word in a sentence (the first line word is the noun indicated by the synonym), The this keyword references the current method in the same way (function, or function) the bound (bound) object. This not only references objects, but also contains object values. Like a prefix, this can also be understood as a shortcut in the context to reference the current object (also known as a "prefix object") (or a substitute to moderately reduce ambiguity ). We will talk about the "context" later ".

Basic Theory of this keyword

First, we need to know that objects have properties, and all functions also have attribute sets. When a method is run, a this attribute is available-a variable that stores the value of an object that calls this method (precisely the method using the this keyword.

This keyword always points to an object and holds the value of this object, although it can appear outside of the global scope (function, but it usually appears in the method body. It is worth noting that if we use strict mode and use the this keyword in a global method or an anonymous method that is not bound to any object, this will point to undefined.

This is used in the method body. For example, method A points to the value of the object that calls method. In no case can we find the name of the object that calls method A. In this case, we use this to access the methods and attributes of the object that calls method. This is indeed just a shortcut to reference the first line word-the object that calls the method.

Let's take a closer look at the following code for using this.

Var person = {firstName: "Penelope", lastName: "Barrymore", // this is used in the showFullName method, while showFullName is defined in the person object, because showFullName is called by the person object, this has the value of showFullName: function () {console. log (this. firstName + "" + this. lastName) ;}} person. showFullName (); // result: Penelope Barrymore

Consider the jQuery example using this in the following section.

// This is a 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 explain in detail the above jQuery example: $ (this). this is the jQuery version of this, which is used in anonymous methods, this anonymous method is executed in the button click event. $ (This) is bound to the button object because the jQuery library binds $ (this) to the object that calls the click method. Therefore, although $ (this) is defined in an anonymous method that cannot access the "itself" variable, $ (this) still points to the button object.

Note that a button is a DOM element of an HTML page and an object at the same time: in the above example, because we wrap it in the $ () method of jQuery, so it is a jQuery object.

Core of this keyword

The following rule helps you fully understand the this keyword: if a method uses the this keyword internally, this keyword is assigned only when the object calls this method. We estimate and call the method that uses the this keyword "this method ".

Although it seems that this references the direction in the Code, in fact, it is not assigned a value before the method is called, the value assigned to it is strictly dependent on the object that actually calls the "this method. This is usually assigned the value of the called object. The following are some special cases.

This in the global range

In the global domain, the code is executed in the browser. All variables and Methods belong to the window object. Therefore, when we use the this keyword in the global domain, it will be directed to the (and own) Global Variable window object. As mentioned above, except for strict mode. A window object is a JS program or a main container of a webpage.

Therefore:

Var firstName = "Peter", lastName = "Ally"; function showFullName () {// In this method, this will point to the window object. Because showFullName () appears in the whole area. Console. log (this. firstName + "" + this. lastName);} var person = {firstName: "Penelope", lastName: "Barrymore", showFullName: function () {// the following line of code, this points to the person object, the showFullName method is called by the person object. Console. log (this. firstName + "" + this. lastName) ;}} showFullName (); // Peter Ally // The window object contains all global variables and methods, so the following output window is displayed. showFullName (); // Peter Ally // The showFullName method that uses the this keyword is defined in the person object. The this keyword points to the person object, because the following output is person. showFullName (); // Penelope Barrymore

A trick to deal with this

When the this keyword is used in a method, these situations are most likely to cause misunderstanding: the method is borrowed, the method is assigned to a variable, and the method is used as a callback function ), this is passed as a parameter; the method where this is located is a closure (this method is an internal method ). In these cases, we will break through them one by one. Before that, let's briefly introduce the context ).

The context in JS is similar to the subject in this sentence: "John is the winner and he has paid back ". The subject of this sentence is John. We can also say that the context of this sentence is John, because we pay attention to John in this sentence, even if there is a word "he" here to represent John's preference. Just as we can use semicolons to switch the subject of a sentence, by using different objects to call methods, the current context object can also be switched.

Similarly, the following JS Code:

Var person = {firstName: "Penelope", lastName: "Barrymore", showFullName: function () {// context console. log (this. firstName + "" + this. lastName) ;}}// when showFullName is called using the person object, the context is the person object // this inside showFullName points to the person object person. showFullName (); // Penelope Barrymore // if we use different objects to call showFullNamevar anotherPerson = {firstName: "Rohit", lastName: "Khan "}; // We can use the apply method to explicitly set the value of this-later we will talk about the apply method // this will point to any object that calls this method, therefore, the following output result is person. showFullName. apply (anotherPerson); // Rohit Khan // so the current context is anotherPerson, because anotherPerson indirectly calls the showFullName method of person by using the apply method.

Now we will officially discuss the tricks to deal with the this keyword. The example contains the errors and solutions caused by this.

1. When this is used as a callback function to pass in other methods

When we take a method that uses the this keyword as a parameter as a return function, the trouble arises. For example:

// The following is a simple object. We define a clickHandler method. We want this method to be executed when a button is clicked on the page. Var user = {data: [{name: "T. woods ", age: 37}, {name:" P. mickelson ", age: 43}], clickHandler: function (event) {var randomNum = (Math. random () * 2 | 0) + 1)-1; // random return 0 or 1 // the following line of code will randomly print the name and age console from the array data. log (this. data [randomNum]. name + "" + this. data [randomNum]. age) ;}}// the button object is encapsulated by jQuery's $ method and is now a jQuery object // so the output result is undefined, because the button object does not have the data attribute $ ("button "). click (user. clickHandler); // undefined attributes cannot be read

In the above Code, we use user. clickHandler as the callback function to input the click Event of the $ ("button") object. this in user. clickHandler will not point to the user object for conversion. Who calls this method containing this will point to WHO. The object that actually calls user. clickHandler is the button object-user. clickHandler, which will be executed in the click method of the button object.

Note that although we use user. clickHandler calls the clickHander method (we can only do this because clickHandler is defined on the user object). The clickHandler method itself is called by the context object that this points. Therefore, this now points to the $ ("button") object.

When the context changes-when we execute a method on another object rather than the original object, it is clear that this keyword does not point to the original object that defines the this keyword.

Solution:

Because we really want this. data to point to the data attribute of the user object, we can use Bind, Apply, Call, and other methods to forcibly change the object that this points. Other articles in this series will specifically explain Bind/Apply/Call. this article describes how to force change the value of this in different situations. I strongly recommend that you read other articles directly instead of discussing them in this article ").

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 use the bind method to bind the clickHandler to the user object:

$ ("Button"). click (user. clickHandler. bind (user); // P. Mickelson 43
2. this IN THE CLOSURE

Using this in internal methods or closures is another example that is easily misunderstood. We must note that internal methods cannot directly use the this keyword to access this variable of external methods, because this variable can only be used by specific methods. For example:

Var user = {tournament: "The Masters", data: [{name: "T. woods ", age: 37}, {name:" P. mickelson ", age: 43}], clickHandler: function () {// use this. data is not too problematic, because this points to the user object, and data is a property of the user. this. data. forEach (function (person) {// but in this anonymous method (this method is passed as a parameter to the forEach method, this does not point to the user object. // The internal method cannot access this console of the external method. log ("What is This referring? "+ This); // The output result 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 "this" referring? [Object Window]

Because this in the anonymous method cannot access this in the external method, this points to the global window object in non-strict mode.

Solution:

Before entering the forEach method, an additional variable is used to reference this.

Var user = {tournament: "The Masters", data: [{name: "T. woods ", age: 37}, {name:" P. mickelson ", age: 43}], clickHandler: function (event) {// to capture the value when this points to the user object, we assign it to another variable theUserObj, we can use theUserObj var theUserObj = this; this. data. forEach (function (person) {// now we don't need 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 in the following code, many JS developers prefer to use the variable that to set the value of this. However, I personally do not like to use that name. I like to use it to understand at a glance who this actually points to, so I used theUserObj = this in the above Code.

// This code is more common for most JS developers than var that = this;

3. The method is assigned to a variable.

This keyword is sometimes very naughty. If we assign a method using this keyword to a variable, let's see what is interesting:

// The data variable is a global variable.
Var data = [{
Name: "Samantha ",
Age: 12
},
{
Name: "Alexis ",
Age: 14
}];

Var user = {
// The data here is an attribute of the 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
// The name and age are randomly displayed 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;

// Execute the showUserData method, and the result will be from the global data array instead of the data Attribute of the user object
ShowUserData (); // Samantha 12 (from the 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 );

// Now the result will be from the user object, because the this keyword has been forcibly bound to the user object.
ShowUserData (); // P. Mickelson 43

4. Problems arising from borrow Methods

In JS development, the borrow method (borrowing methods) is very common.

Let's look at the following code:

// The following Code contains two objects. One of them defines the avg method, and the other does not include 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 the execution In the following code, the actual value of the gameController. avgScore attribute will come from scores of appController. // 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. If appController is used to call this method, this will point to appController (but in fact this is not the expected result, because we only want to borrow the implementation logic of the method rather than the specific data source ).

Solution:

To ensure that gameController only uses the logic of the avg method of appController, we use the apply method:

// We need to use the apply method. Note that the appController is input here. appController, the second parameter of the avg method. avg. apply (gameController, gameController. scores); // although the avg method is borrowed, The avgScore attribute has been successfully applied to the gameController. Console. log (gameController. avgScore); // 46.4 // appController. avgScore is still null. Only the avgScore of gameController is updated to console. log (appController. avgScore); // null

GameController only uses the avg method of appController. this will point to gameController, because gameController is passed as the first parameter of the apply method. The first parameter of the apply method explicitly sets the value of this.

Conclusion

Hope you have some gains in this article. Now you can use the tricks described in this article (bind method, apply method, call method, and assign this value to a variable) to deal with any problems related to this.

As we have learned, this is used as a callback function, called by different objects, or borrowed methods when the context changes, this will always point to the object that calls the current method.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.