Some pits of this in JavaScript

Source: Internet
Author: User

We often encounter some pits in the callback function:

var obj = {  name: ‘qiutc‘,  foo: function() {    console.log(this);  },  foo2: function() {    console.log(this);    setTimeout(this.foo, 1000);  }  }obj.foo2();

Executing this code we will find that two times the print out this is not the same:

The first time is foo2 in direct print this , here Point obj to this object, we have no doubt;

But in setTimeoutExecuted in thethis.foo, but it points to the global object, does this not use it as a function method? This is often confusing to many beginners;setTimeoutIt's just a function, and the function is bound to require arguments, and we putthis.foo  as a parameter to   setTimeout   this function, just as it requires a   Fun   parameters, when passed in the parameters, in fact, did an operation fun = This.foo , see no, here we directly put fun   point to  , this.foo   references The execution of the   fun ()   obj   this   points to the global object.

This problem is commonly encountered in many asynchronous callback functions;

Solve

To solve this problem, we can use the characteristics of closures to deal with:

var obj = {  name: ‘qiutc‘,  foo: function() {    console.log(this);  },  foo2: function() {    console.log(this);    var _this = this;    setTimeout(function() {      console.log(this);        console.log(_this);      }, 1000);  }  }obj.foo2();

Can be seen directly with the this still is, Window because the foo2 this Point is obj , we can first use a variable _this to store, Then use it in the callback function to point to the _this current object;

Use as a constructor

In JS, in order to implement the class, we need to define some constructors, when calling a constructor, we need to add new this keyword:

function Person(name) {  this.name = name;  console.log(this);  }var p = new Person(‘qiutc‘);

We can see that when called as a constructor, it points to the object that is this instantiated when the constructor is called;

Of course, the constructor is actually a function, and if we take it as a normal function, this this still performs the global:

function Person(name) {  this.name = name;  console.log(this);  }var p = Person(‘qiutc‘);

The difference is how the function () is called new .

Arrow functions

In the new specification of ES6, the arrow function is added, which is the most unusual point of the normal function, and this Remember in the above (as the method call of the object-some pits-solve) we use closures to solve this The point of the problem, If you use the arrow function, you can solve the problem more perfectly:

var obj = {  name: ‘qiutc‘,  foo: function() {    console.log(this);  },  foo2: function() {    console.log(this);    setTimeout(() => {      console.log(this);      }, 1000);  }  }obj.foo2();

As you can see, in the setTimeout execution of the function, it should have been printed out Window , but this pointed obj here setTimeout , the reason is that The passed-in function (parameter) is an arrow function:

The This object in the body of the function is the object that is defined, not the object that is used.

Let's take a look at the following sentence:obj.foo2()At the time of execution, the currentthis  points to   obj ; SetTimeout   time, we first defined an anonymous arrow function, the key point is here, the arrow function inside the &NBSP; this   The object in which the definition is executed is the   that defines the arrow function when it is defined; this , which is &NBSP; obj.foo2   in this , which is   obj ; So when you execute the arrow function, it's &NBSP; this  ->< Span class= "Apple-converted-space" >&NBSP; obj.foo2 this  - >  obj ;

Simply put, the this in the arrow function is only relevant to the scope that defines it, not to where and how it is called, while its this point is immutable.

Call, apply, bind

In JS, the function is also an object, there are also some methods, here we introduce three methods, they can change the point in the function this :

    • Pager
      fun.call(thisArg[, arg1[, arg2[, ...]]])

It executes the function immediately, the first parameter is the context in the specified execution function this , and the following argument is the parameter that the function needs to pass in;

    • Apply
      fun.apply(thisArg[, [arg1, arg2, ...]])

It executes the function immediately, the first parameter is the context in the specified execution function this , the second argument is an array, and is the argument to the execution function ( call the difference);

    • Bind
      var foo = fun.bind(thisArg[, arg1[, arg2[, ...]]]);

It does not execute the function, but instead returns a new function, the new function is specified by the this context, and the following arguments are the parameters that the function needs to pass in;

These three functions are actually very similar, the general purpose is to specify a function of the context (this), we take the call function as an example;

Specify this for a normal function
var obj = {  name: ‘qiutc‘  };function foo() {  console.log(this);  }foo.call(obj);

As you can see, in the execution foo.call(obj) , the function points to the this obj object and succeeds;

Specify a this for the methods in the object
var obj = {  name: ‘qiutc‘,  foo: function () {    console.log(this);  }  }var obj2 = {  name: ‘tcqiu222222‘  };obj.foo.call(obj2);

As you can see, the execution of the function here this points to a obj2 success;

Specify this for the constructor function
function Person(name) {  this.name = name;  console.log(this);  }var obj = {  name: ‘qiutc2222222‘  };var p = new Person.call(obj, ‘qiutc‘);

Here's a mistake, because we went to the new Person.call function, not the Person function Here is not a constructor;

bind Try it:

function Person(name) {  this.name = name;  console.log(this);  }var obj = {  name: ‘qiutc2222222‘  };var Person2 = Person.bind(obj);var p = new Person2(‘qiutc‘);console.log(obj);

The

Print is   person   obj   no relationship, and   obj Span class= "Apple-converted-space" >  also has not changed, stating that we give &NBSP; person   specify &NBSP; this   context does not take effect;

Therefore, it can be concluded that using bind to a constructor specifies this that, at the time of new This constructor, the bind function specified this does not take effect;

Of course bind not only can you specify this , but also pass in parameters, let's try this operation:

function Person(name) {  this.name = name;  console.log(this);  }var obj = {  name: ‘qiutc2222222‘  };var Person2 = Person.bind(obj, ‘qiutc111111‘);var p = new Person2(‘qiutc‘);

As you can see, although the designation this does not work, the incoming parameters still work;

Specify this for the arrow function

Let's define a global arrow function, so the arrow function is bound to point to the this Global Object, if the call method is changed this :

var afoo = (a) => {  console.log(a);  console.log(this);  }afoo(1);var obj = {  name: ‘qiutc‘  };afoo.call(obj, 2);

As you can see, the point here is call this not successful, so it can be concluded that the this in the arrow function has been determined by the time it is defined (this is done in the scope that defines it). It has nothing to do with how and where it is called, including actions such as call, apply, bind, and so on, which cannot be changed by this.

Just remember that the arrow function Dafa is good and unchanging this .

Some pits of this in JavaScript

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.