JavaScript this
Yes, this is also a reading note, recording the relevant content of this in the second part of Volume I of JavaScript You Don't Know, with a lot of additions, deletions and personal understanding.
What is this
It's hard to say what this is, but only a mechanism of JavaScript
This is bound at run time, not at writing time. Its context depends on various conditions when the function is called. The binding of this has nothing to do with the position of the function declaration, but depends on the way the function is called
When a function is called, an activity record (execution context) will be created. This record will contain information such as where the function is called (call stack), the function calling method, and the passed in parameters. This is one of the recorded attributes, which will be used during function execution
In other words, this is the binding that occurs when a function is called. What it points to depends entirely on where the function is called
Call location
The call location is where the function is called in the code, not where it is declared. Finding the calling location is "where the function is called"
Analyzing the call stack is all the functions called to reach the current execution location
Binding Rules
How the call location determines the binding object of this during the execution of the function
Find the call location, and how to judge according to the four rules: default binding, implicit binding, explicit binding, and new binding
Default Binding
This rule can be seen as the default rule when other rules cannot be applied
for example
function foo(){ console.log(this.a); } var a=2; foo();
In the code, foo()
It is called directly by using the function reference without any decoration. It can only use the default binding and cannot apply other rules
If it is strict mode, the global object cannot use the default binding, so this will be bound to undefined
Implicit binding
This rule considers whether there is a context object at the call location, or whether it is owned or contained by an object
for example
function foo(){ console.log(this.a); } var obj = { a:2, foo:foo } obj.foo(); // two
When a function is referenced to a context object, the implicit binding rule will bind this in the function call to the context object.
Because calling foo()
This is bound to obj, so this. a is the same as obj. a
Only the top layer or the last layer of gray in the object attribute reference chain affects the call location, such as
function foo(){ console.log(this.a); } var obj2 = { a:32, foo:foo } var obj1 = { a:2, obj2:obj2 } obj1.obj2.foo(); // thirty-two
Explicit binding
When analyzing implicit binding, we must include an attribute pointing to a function in an object, and indirectly reference the function through this attribute, so that this is indirectly (implicitly) bound to the object. If we don't want to include a function reference inside an object, but want to force a function to be called on an object, we can use the call()
and apply()
method
call()
and apply()
The first parameter of is an object. They will bind this object to this, and then specify this when calling the function. Because the binding object of this can be specified directly, it is called explicit binding
for example
function foo(){ console.log(this.a); } var obj = { a:2 }; foo.call(obj); // two
ES5 also provides us with a hard binding method Function.prototype.bind
, as follows
function foo(something){ console.log(this.a,something); return this.a + something; } var obj = { a:2 } var bar = foo.bind(obj); var b = bar(3); // 2 3 console.log(b); // five
New binding
Use new to call the function, or when the constructor is called, the following operations will be automatically executed
1. Create (construct) a completely new object
2. This new object will be linked by executing [Prototype]
3. This new object will be bound to this function call
4. If the function does not return any other object, the function call in the new expression will automatically return this new object
for example
function foo(a){ this.a = a; } var bar = new foo(2); console.log(bar.a);
priority
The default binding priority is the lowest of the four rules
Explicit binding takes precedence over implicit binding
New binding has higher priority than implicit binding
The priority of new binding is higher than that of explicit binding
Judge this
If you want to judge the binding of this to a running function, you need to find the direct calling location of this function. After finding it, you can apply four rules in the following order to determine the binding object of this
1. Called by new? Bind to newly created object
2. Called by call or apply (or bind)? Bind to the specified object
3. Called by the context object? Bind to that context object
4. By default, bind to undefined in strict mode, otherwise bind to global objects
This morphology
There is a special function type in ES6 that cannot apply the four rules mentioned above: arrow function
The arrow function is not defined with the function keyword, but with a fat arrow =>
Defined.
The arrow function does not use the four standard rules of this, but determines this according to the outer (function or global) scope
for example
function foo(){ return(a)=>{ console.log(this.a); }; } var obj1 = { a:2 }; var obj2 = { a:3 }; var bar = foo.call(obj1); bar.call(obj2); // two
foo()
The internally created arrow function will capture the foo()
This. Since this of foo() is bound to obj1, and this of bar is also bound to obj1, the binding of arrow function cannot be modified (nor can new)
Not much content, so far~
This article is written by Chakhsu Lau Creation, adoption Knowledge Sharing Attribution 4.0 International License Agreement.
All articles on this website are original or translated by this website, except for the reprint/source. Please sign your name before reprinting.