Tip: First of all, I know this article is boring. It is nothing more than this in js, and thousands of articles have already written this part. However, I still want to write an article about this in js, which is a summary. (You can refer to my other articles.) In js, the context of this is always unpredictable, in many cases, bugs are always confused. In fact, you only need to clarify the tip.
First of all, I know this article is boring. It is nothing more than this in js, and thousands of articles have already written this Part;
However, I still want to write an article about this in js, which is a summary. (You can refer to my other articles)
In js, the context of this is always unpredictable. In many cases, bugs are always confused. In fact, it is okay to know how to execute it in different situations.
Global execution
First, let's look at what this is in the global environment:
First. Browser:
Console. log (this );
// Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage, sessionStorage: Storage, webkitStorageInfo: DeprecatedStorageInfo ...}
The output is
window
Object;
Second. node:
Console. log (this );
// Global
The output is
global
Object;
Summary: In the global scope, its
this
Execute the current global object (the browser side is
Window
In node
global
).
Execute pure function calls in Functions
This is the most common function usage method:
Function test (){
Console. log (this );
};
Test ();
// Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage, sessionStorage: Storage, webkitStorageInfo: DeprecatedStorageInfo ...}
We can see that when a function is called directly, it is a global call.
this
Point to a global object;
Strict mode 'use strict ';
If you execute pure function calls in strict mode
this
It does not point to the global,
undefined
To eliminate some of the less rigorous JavaScript behaviors:
'Use strict ';
Function test (){
Console. log (this );
};
Test ();
// Undefined
Of course, it would be better to put it in an immediate execution function to avoid global contamination:
(Function (){
"Use strict ";
Console. log (this );
})();
// Undefined
Method call as an object
When a function is called as a method of an object:
Var obj = {
Name: 'qiut ',
Foo: function (){
Console. log (this. name );
}
}
Obj. foo ();
// 'Qiutc'
At this time,
this
Point to the current object;
Of course, we can also do this:
Function test (){
Console. log (this. name );
}
Var obj = {
Name: 'qiut ',
Foo: test
}
Obj. foo ();
// 'Qiutc'
It remains unchanged because everything in js is an object, and a function is also an object.
test
, It is just a function name, a function reference, it points to this function, when
foo = test
,
foo
It also points to this function.
If you assign an object method to a variable and then call the variable directly:
Var obj = {
Name: 'qiut ',
Foo: function (){
Console. log (this );
}
}
Var test = obj. foo;
Test ();
// Window
We can see that at this time
this
The global execution is performed.
test = obj.foo
,
test
Directly pointing to a function reference. In this case
obj
This object does not matter, so it is directly called as a common function. Therefore,
this
Point to a global object.
Pitfalls
We often encounter some pitfalls in the callback function:
Var obj = {
Name: 'qiut ',
Foo: function (){
Console. log (this );
},
Foo2: function (){
Console. log (this );
SetTimeout (this. foo, 1000 );
}
}
Obj. foo2 ();
After executing this code, we will find that
this
Is different:
The first time is
foo2
Directly print
this
, Pointing
obj
This object is beyond doubt;
However
setTimeout
Executed in
this.foo
But it points to a global object. Isn't it used as a function? This is often confusing for beginners;
In fact,
setTimeout
It is just a function, and the function may need parameters.
this.foo
Passed as a parameter
setTimeout
This function, just as it needs
fun
Parameter. During parameter input, this operation is actually performed.
fun = this.foo
.
fun
Point
this.foo
Is actually executed.
fun()
Therefore
obj
It is called directly as a common function. Therefore
this
Point to a global object.
This problem is common in many asynchronous callback functions;
Solution
To solve this problem, we can use the closure feature to handle it:
Var obj = {
Name: 'qiut ',
Foo: function (){
Console. log (this );
},
Foo2: function (){
Console. log (this );
Var _ this = this;
SetTimeout (function (){
Console. log (this); // Window
Console. log (_ this); // Object {name: "qiutc "}
},1000 );
}
}
Obj. foo2 ();
You can see that
this
Still yes
Window
Because
foo2
In
this
Yes
obj
, We can use a variable
_this
And then use it in the callback function.
_this
To point to the current object;
Another pitfall of setTimeout
Previously, if the callback function is directly executed without binding the scope
this
Is a Global Object (
window
In strict mode.
undefined
However
setTimeout
The callback functions in strict mode are different:
'Use strict ';
Function foo (){
Console. log (this );
}
SetTimeout (foo, 1 );
// Window
The strict mode is added, and the foo call is not specified.
this
, It should be
undefined
But there are still global objects. Is the strict mode invalid?
No, even in strict mode,
setTimeout
Method when calling the input function, if this function is not specified
this
Then it performs an implicit operation -- automatically injects the global context, which is equivalent to calling
foo.apply(window)
Rather
foo()
;
Of course, if we have specified
this
So that global objects are not injected, such:
setTimeout(foo.bind(obj), 1);
Used as a constructor
In js, to implement classes, 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 ('qiut ');
// Person {name: "qiutc "}
We can see that when called as a constructor,
this
Points to the object instantiated during the call of this constructor;
Of course, constructor is actually a function. If we treat it as a normal function, this
this
Still execute Global:
Function Person (name ){
This. name = name;
Console. log (this );
}
Var p = Person ('qiut ');
// Window
The difference is that how to call a function (
new
).
Arrow Function
In the new ES6 specification, an arrow function is added, which is the most different from a common function.
this
We still remember to use the closure to solve this problem.
this
If the arrow function is used, the problem can be solved more perfectly:
Var obj = {
Name: 'qiut ',
Foo: function (){
Console. log (this );
},
Foo2: function (){
Console. log (this );
SetTimeout () => {
Console. log (this); // Object {name: "qiutc "}
},1000 );
}
}
Obj. foo2 ();
As you can see
setTimeout
In the executed function, it should have been printed in
Window
But here
this
But points
obj
The reason is:
setTimeout
The input function (parameter) is an arrow function:
This object in the function body is the object in the definition, rather than the object in use.
Based on the example, we can understand this sentence:
In
obj.foo2()
During execution, the current
this
Point
obj
; In execution
setTimeout
First, we define an anonymous arrow function. The key point is here.
this
The object in which the definition is executed refers to the objects in the scope when the arrow function is defined.
this
, That is
obj.foo2
In
this
, That is
obj
So when executing the arrow function, its
this
->
This in obj. foo2
->
obj
;
In simple terms, this in the arrow function is only related to the scope of this when it is defined, and has nothing to do with where and how to call it. At the same time, its this point cannot be changed.
Call, apply, bind
In js, functions are also objects, and there are also some methods. Here we will introduce three methods, they can change
this
Point:
Call
Fun. call (thisArg [, arg1 [, arg2 [,...])
It will immediately execute the function. The first parameter is to specify the execution function
this
The following parameters are the parameters that need to be passed in to the execution function;
Apply
Fun. apply (thisArg [, [arg1, arg2,...])
It will immediately execute the function. The first parameter is to specify the execution function
this
The second parameter is an array, which is the parameter passed to the execution function (
call
);
Bind
Var foo = fun. bind (thisArg [, arg1 [, arg2 [,...]);
Instead of executing the function, it returns a new function, which is specified
this
The following parameters are the parameters that need to be passed in to the execution function;
These three functions are similar in fact. The general purpose is to specify the context (this) of a function.
call
The function is used as an example;
Specify this for a Common Function
Var obj = {
Name: 'qiutc'
};
Function foo (){
Console. log (this );
}
Foo. call (obj );
// Object {name: "qiutc "}
As you can see
foo.call(obj)
In the Function
this
Pointed
obj
This object is successful;
Specify
Var obj = {
Name: 'qiut ',
Foo: function (){
Console. log (this );
}
}
Var obj2 = {
Name: 'tcqiu22222222'
};
Obj. foo. call (obj2 );
// Object {name: "tcqiu222222 "}
We can see that during function execution
this
Pointed
obj2
, Succeeded;
Specify this for the constructor
Function Person (name ){
This. name = name;
Console. log (this );
}
Var obj = {
Name: 'qiutc2222222'
};
Var p = new Person. call (obj, 'qiutc ');
// Uncaught TypeError: Person. call is not a constructor (...)
An error is reported because
new
Now
Person.call
Function, rather
Person
, The function here is not a constructor;
Change
bind
Try:
Function Person (name ){
This. name = name;
Console. log (this );
}
Var obj = {
Name: 'qiutc2222222'
};
Var Person2 = Person. bind (obj );
Var p = new Person2 ('qiut ');
// Person {name: "qiutc "}
Console. log (obj );
// Object {name: "qiutc2222222 "}
The output is
Person
And
obj
It doesn't matter, and
obj
No changes.
Person
Specify
this
The context does not take effect;
Therefore, we can conclude that bind is used to specify a constructor.
this
, In
new
During this constructor,
bind
The
this
Does not take effect;
Of course
bind
You can specify
this
You can also input parameters. Let's try this operation:
Function Person (name ){
This. name = name;
Console. log (this );
}
Var obj = {
Name: 'qiutc2222222'
};
Var Person2 = Person. bind (obj, 'qiutc11111111 ');
Var p = new Person2 ('qiut ');
// Person {name: "qiutc111111 "}
As you can see, although
this
Does not work, but the input parameter still works;
Specify this for the arrow Function
Define a global arrow function.
this
It will inevitably point to the global object.
call
Method change
this
What about:
Var afoo = (a) => {
Console. log ();
Console. log (this );
}
Afoo (1 );
// 1
// Window
Var obj = {
Name: 'qiutc'
};
Afoo. call (obj, 2 );
// 2
// Window
We can see that
call
Point
this
The operation is not successful, so it can be concluded that this in the arrow function has decided when defining it (executing this in its scope ), it has nothing to do with how to call and where to call it, including (call, apply, bind) and other operations. this cannot be changed.
Just remember the arrow function.
this
The above is the detailed description of this in JavaScript. For more information, see other related articles in the first PHP community!