Executing in the global
Let's see what this is in the global.
first, in the browser :
Console.log (this); // Window {speechsynthesis:speechsynthesis, caches:cachestorage, Localstorage:storage, Sessionstorage:storage, Webkitstorageinfo:deprecatedstorageinfo ...}
Visible, in the browser this point to window
second, in node :
Console.log (this); // Global
In node, this points to global
Summary : It executes the current global object in the global scope (the browser side is global in Window,node).
Executing in a function
Purely function calls
function Test () { console.log (this// Window {speechsynthesis: Speechsynthesis, Caches:cachestorage, Localstorage:storage, Sessionstorage:storage, WebkitStorageInfo: Deprecatedstorageinfo ...}
Strict mode ' use strict '
"Use strict" function foo () { Console.log (this);} Foo (); // undefined
Of course, it would be better to put it in your own execution function using "use strict" to avoid contaminating the global
(Functuon () { "use strict" Console.log (this);}) (); // undefined
Method invocation as an object
var obj = { ' QIUTC ', function() { Console.log (this . Name); // ' QIUTC '
This time, this point points to the current object;
Of course, we can also do this:
function Test () { Console.log (this. name);} var obj = { ' QIUTC ', // ' QIUTC '
If you copy the object's methods directly to a variable to which to go, see
var obj = { ' QIUTC ', function() { Console.log (this ); var test =// Window
As you can see, this points to the window, where test points to a reference to the Obj.foo function, which is irrelevant to the Obj object, and test is a global variable, so test () is called as a normal function, so this is a point to the window.
Some pits
var obj = { ' QIUTC ', function() { Console.log (this ); }, function() { Console.log (this); SetTimeout (this. Foo, +); }} Obj.foo2 ();
Executing this code we will find that two times the print out of this is not the same:
For the first time, this is printed directly in Foo2, which points to the Obj object, which we have no doubt;
But This.foo, which executes in setTimeout, points to the global object, isn't it used as a function method? This often makes many beginners puzzled;
In fact, SetTimeout is just a function, the function is necessarily likely to need parameters, we put This.foo as a parameter to setTimeout this function, as it needs a fun parameter, when passed in the parameters, in fact, did a such operation fun = This.foo, see no, here we direct the fun point to the This.foo reference, the execution of the time is actually executed fun () so it has nothing to do with obj, it is called as a normal function directly, so this point 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:
varobj ={name:' QIUTC ', foo:function() {Console.log ( This); }, Foo2:function() {Console.log ( This); var_this = This; SetTimeout (function() {Console.log ( This);//WindowConsole.log (_this); //Object {name: "QIUTC"}}, 1000); }} obj.foo2 ();
Can be seen directly with this is still the Window; because this in foo2 points to obj, we can store it with a variable _this first, then use _this in the callback function to point to the current object;
Another pit of SetTimeout.
Before that, if you execute the callback function directly without the binding scope, then it is pointing to the Global Object (window), and in strict mode it points to undefined, but the callback function in SetTimeout behaves differently in strict mode.
' Use strict 'function foo () { Console.log (this1// window
Supposedly we added strict mode, Foo call also did not specify this, should be out undefined, but here still appear global object, is strict mode invalid?
No, even in strict mode, when the SetTimeout method calls an incoming function, if the function has no specified this, then it does an implicit operation-automatically injecting the global context, equivalent to calling foo.apply (window) rather than foo ();
Of course, if we have specified this when passing in the function, then we will not be injected into the global object, for example: SetTimeout (Foo.bind (obj), 1);
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 the New keyword:
function Person (name) { this. Name= name; Console.log (this varnew person (' QIUTC '// person {name: "QIUTC"}
We can see that when called as a constructor, this points to the object instantiated by the constructor call;
Of course, the constructor is actually a function, and if we take it as a normal function, this one still performs the global:
function Person (name) { this. Name= name; Console.log (this var p = person (' QIUTC '// Window
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 different from the normal function is the point of this, remember in the above (as the object of the method call-some pits-solve) we use closures to solve the problem of this point, if the use of the arrow function can be more perfect solution:
var obj = { ' QIUTC ', function() { Console.log (this ); }, function() { Console.log (this); = = { Console.log (this); // Object {name: "QIUTC"} }, +);} } Obj.foo2 ();
As you can see, in the function that setTimeout executes, it should have been printed in Window, but here this is pointing to obj, because the function (parameter) passed to SetTimeout 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 this sentence by example:
At the time of Obj.foo2 () execution, the current this point points to obj, and in the execution of SetTimeout, we first define an anonymous arrow function, where the key is the object in which this is defined when the this arrow function is defined, which is the scope of the This, which is the this in Obj.foo2, that is, obj; so when the arrow function is executed, it's this------and obj in Obj.foo2;
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 function of this point:
Pager
Fun.call (thisarg[, arg1[, arg2[, ...])
It executes the function immediately, the first parameter is the context that specifies the this in the execution function, and the following arguments are the parameters that the function needs to pass in;
Apply
Fun.apply (thisarg[, [Arg1, Arg2, ...])
It executes the function immediately, the first parameter is the context that specifies the this in the execution function, the second argument is an array, and is the argument to the execution function (the difference from call);
Bind
var foo = fun.bind (thisarg[, arg1[, arg2[, ...]);
Instead of executing the function, it returns a new function that is assigned the context of this, and the arguments that follow are the parameters that the function needs to pass in;
These three functions are actually quite similar, the general purpose is to specify a function context (this), we take the call function as an example;
Specify this for a normal function
var obj = { ' qiutc 'function foo () { Console.log (this // Object {name: "QIUTC"}
As you can see, in the execution of Foo.call (obj), this object in the function points to obj, which is successful;
Specify a this for the methods in the object
var obj = { ' QIUTC ', function () { Console.log (this ); var obj2 = { ' tcqiu222222 '// Object {name: "tcqiu222222"}
As you can see, this is where the function is executed, which points to the OBJ2, success;
Specify this for the constructor function
function Person (name) { this. Name= name; Console.log (thisvar obj = { ' qiutc2222222 'var New Person.call (obj, ' qiutc '// uncaught TypeError:Person.call is not a constructor (...)
Here's a mistake because we went to new Person.call function, not person, here is not a constructor function;
Change to bind try:
function person (name) { this . Name = name; Console.log ( this var obj = {name: ' qiutc2222222 ' Span style= "COLOR: #000000" >}; var Person2 = Person.bind (obj); var p = new Person2 (' QIUTC ' ); // person {name: "QIUTC"} Console.log (obj); // Object {name: "qiutc2222222"}
The printed object is instantiated by the person, and obj has no relation, and obj has not changed, stating that we have given the person the this context is not in effect;
Therefore, it can be concluded that by using bind to assign this to a constructor, the this specified by the BIND function does not take effect at the time of the new constructor .
Of course bind can not only specify this, but also pass in parameters, let's try this operation:
function Person (name) { this. Name= name; Console.log (thisvar obj = { ' qiutc2222222 'var Person2 = Person.bind (obj, ' qiutc111111 'varnew Person2 (' QIUTC '// person {name: "qiutc111111"}
As you can see, although specifying this does not work, the incoming parameters still work;
Specify this for the arrow function
Let's define a global arrow function, so this one in the arrow function will necessarily point to the global object, and if you change this with the call method:
var afoo = (a) + = { console.log (a); Console.log (this);} Afoo (1// 1// Windowvar obj = { ' QIUTC '2// 2// Window
As you can see, the call to this here is not successful, so it can be concluded that the this in the arrow function has been determined at the time it was defined (this in the scope where it was defined), regardless of how and where it was called, including (calls, apply, b IND) cannot change its this.
Just remember the arrow function Dafa good, unchanging this.
The This in Javascript