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 setTimeout
Executed 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;setTimeout
It'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   this
The object in which the definition is executed is the that defines the arrow function when it is defined; this
, which is   obj.foo2
in this
, which is obj
; So when you execute the arrow function, it's   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
:
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;
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);
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