Proficient in JavaScript this keyword _javascript tips

Source: Internet
Author: User
Tags prev jquery library

JS in the This keyword so many new and old JS developers are confused. This article will be fully elaborated on this keyword. After reading this article, your confusion will all be eliminated. You will learn how to use this correctly in a variety of different situations.

We use this as a noun in natural languages such as English and French. For example, "John ran fast because he wanted to catch the train." Please pay attention to the pronoun "he" in this sentence of substituting John. We could have said that, "John ran fast because John wanted to catch the train." According to normal language habits, we do not express in the second way. If we really speak the second way, our family and our base friends will definitely treat us as freaks. Perhaps not only the family, even our fair-weather friends 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 points to the principal (subject) of the current context, which will be interpreted specifically in the context below, 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 use "he" As a synonym, we use this console.log here

   (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, in a global variable, there is a variable name with the same name as person. In this case, if we want to read the Person.firstname value, 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 debugging code. So this does not only play the role of beautifying the code, but also to ensure the accuracy of the program. This practice is actually the same as the previous "he" usage, making our code clearer. "he" was quoted as "John" at the beginning of the sentence.

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 in the same way to the object of the current method (function, also known as functions) bound (bound). This does not just refer to the object, it also contains the value of the object. As with the antecedent, this can also be interpreted as a shortcut to the context in which the current object (also called the "antecedent object") is referenced (or a substitute for a moderately reduced ambiguity). We'll explain the context later.

This keyword basic theory

The first thing we need to know is that objects (object) have attribute sets (properties), and all methods (function) also have attribute sets. When you run to a method, you have a This property-a variable that stores the value of the object that called the method (precisely the method that uses 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 worth noting that if we use the This keyword in the strict mode (strict mode) and in the global Method (functions) or in an anonymous method that is 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 calling 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 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 code that uses this in the following section.

var person = {
  FirstName: "Penelope",
  lastName: "Barrymore",
  //this used in the Showfullname method, and showfullname is defined in the person object, because the call Showfullname is the object of person, so this has the value of person

  showfullname:function () {
    Console.log (This.firstname + "" + This.lastname);
  }
Person.showfullname (); Results: Penelope Barrymore

Consider the following jquery example that uses this.

This is a very simple jquery code

$ ("button"). Click (The function (event) {
  //$ (this) points to the $ ("button") object
  //Because $ ("button") Object invokes the click Method
  Console.log ($ (this). Prop ("name"))
;

I want to say a little bit more about this jquery example: $ (this) is used, this is the jquery version of this, which is used in the anonymous method, which is executed in the Click event of the button. The reason for this is that the $ (this) is bound to the button object because the jquery library binds the $ (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 is an object: In the above example, because we wrap it in the jquery $ () method, it is a jquery object.

The core of this keyword

Here's a rule that will help you understand this keyword thoroughly: If the This keyword is used internally by a method, the This keyword is assigned only when the object invokes the method. We estimate and refer to the method using the This keyword as the "this method".

Although this seems to refer to the alignment it exists in the code, it is actually not assigned until 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 there 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. Thus, when we use the This keyword in the global domain, it is pointed to (and owns) the global Variable Window object. As mentioned earlier, the strict mode is the exception. The Window object is the main container for a JS 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: "Barrymore",
  showfullname:function () {
    //The following line of code, This points to the person object because the Showfullname method is invoked by the person object.
    Console.log (This.firstname + "" + This.lastname);
  }

Showfullname (); The Peter Ally

//window object contains all of the global variables and methods, so there will be the following output
window.showfullname ();//Peter Ally

// The Showfullname method that uses the This keyword is defined in the person object, and the This keyword points to the person object because of the following output
person.showfullname ();//Penelope Barrymore

There's a trick to dealing with this.

When 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, and the method is used as a callback function (callback) and is passed as a parameter; This is the method that is a closed package (the method is an internal method). In these cases, we will break through. Before that, let's start with a brief introduction to the context.

The context in JS is similar to the subject in this sentence (subject): "John is the winner, he pays the money." John is the subject of this sentence. 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" to refer to the word John this antecedent. Just as we can use semicolons 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 using the person object to invoke Showfullname, the context is the inside of the person object//showfullname to point to the person
object
person.showfullname (); Penelope Barrymore
//If we use different objects to invoke Showfullname
var Anotherperson = {
  firstName: "Rohit",
  LastName: "Khan"
};

We can use the Apply method to set the value of this explicitly-later we'll talk about the Apply method
//this will point to any object that calls the This method, so the following output
will be Person.showFullName.apply (Anotherperson); Rohit Khan
//So now the context is Anotherperson, because Anotherperson the Showfullname method of indirectly invoking the person by using the Apply method

Now we are formally discussing the trick to deal with this keyword, which contains the errors and solutions raised by this.

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

The trouble comes when we use the This keyword as a parameter as a return function. For example:

Here is a simple object, and we define a ClickHandler method. We want this method to execute 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
    //below this line generation The code randomly prints the name and age Console.log from the array data
    (This.data[randomnum].name + "" + this.data[randomnum].age)
  ;
}

The button object is packaged in jquery's $ method and now becomes a jquery object
//So the output result is undefined because the button object has no data this attribute
$ ("button"). Click ( User.clickhandler); Unable to read undefined attribute

In the code above, we use User.clickhandler as the callback function to pass in the click event of the $ ("button") object, and this in User.clickhandler will no longer point to the user object. Who called this method containing this will point to WHO. The object that really calls User.clickhandler is the button object-user.clickhandler executes 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 invoked by the context object now pointed to by this. So this is now pointing to the $ ("button") object.

When 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 the change to the object that this is pointing to. The other titles in this series will be devoted to Bind/apply/call, which describes how to force the change of this value in different situations. Rather than having a big discussion in this article, I strongly recommend that you read the other titles directly: 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 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 access the this variable of an external method by using the This keyword, because this variable can only be used by a particular method itself. For example:

var user = {
  tournament: "The Masters",
  data: [{
    name: "T. Woods",
    age:37
  },
  {
    name: "P. Mic" Kelson ",
    age:43
  }],

  clickhandler:function () {
    // It's not much of a problem to use this.data in, because this refers to the user object, and data is a property of user
    This.data.forEach (function (person) {
      / However, in this anonymous method (which is passed as a parameter to this method of the Foreach method), this does not point to the User object
      //internal method cannot access the this console.log of the external method
      ("What is") Referring to? "+ this); The output result is: [Object Window]
      console.log (Person.name + ' is playing at "+ this.tournament);
      T. Woods is playing at undefined
      //P. Mickelson are playing at undefined
    }}

}

User.clickhand Ler (); What is ' this ' referring to? [Object Window]

Because this in the anonymous method does not have access to this of the external method, this refers to the global window object in non-strict mode

Solution:

Use an extra variable to refer to this before entering the Foreach method.

var user = {
  tournament: "The Masters",
  data: [{
    name: "T. Woods",
    age:37
  },
  {
    name: "P. Mic" Kelson ",
    age:43
  }],

  clickhandler:function (event) {
    //To capture the value of this point to the user object, We assign it to another variable theuserobj, which we can use 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 are playing at the Masters

As the following code, many JS developers like to use variable that to set this value. But I personally do not like the name of that, I like to use the one-glance to see who the end of the name, so the above code I used Theuserobj = this.

 This code is more common to most JS developers than the "
var" = this;

3. Method is assigned to a variable

This keyword is sometimes naughty, and if we assign a value to a variable using the This keyword, we'll 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 generated 1 or 0
This sentence will randomly display the name and age of the person 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, with the result coming from the global data array rather than the user object's Data property
Showuserdata (); Samantha 12 (from global variable data)
Solution: To explicitly set this value 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 forcibly bound to the user object.
Showuserdata (); P. Mickelson 43

4. Problems arising from borrowing methods

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

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 from the previous object.
var gamecontroller = {
  scores: [A, M, MB, m],
  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 = th Is.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 come from the scores of AppController and
do not execute the following code, we just want to explain this situation. In fact, we want to keep 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 invoked using AppController, this will point to AppController (but in fact this is not the result we expected, Because we only 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, note here the second parameter of the Appcontroller.avg method
appController.avg.apply (Gamecontroller, Gamecontroller.scores);

Although the Avg method is borrowed, the Avgscore attribute has now been successfully applied to the Gamecontroller.
Console.log (Gamecontroller.avgscore);//46.4
// Appcontroller.avgscore is still null, and only Gamecontroller Avgscore has been updated
Console.log (appcontroller.avgscore);//null

Gamecontroller only borrowed the AppController Avg method, and this will point to Gamecontroller, as we pass 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 some results in the article. Now you can use the ACE (Bind method, apply method, call method, and assign this to a variable) in the article to deal with any problem related to this.

As has been learned, this will always point to the object calling the current method when the context changes, is used as a callback function, is invoked by a different object, or the method is borrowed.

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.