this keyword pit. Whenever a function is defined,
this is automatically defined inside the function (even if the
this keyword is not used inside the function).
Function call location
this, let’s understand function call location. The call position of a function is where the function is called, not where it is declared. In order to understand call location, it is important to analyze a function’s call stack , which is a chain of function executions, to understand the call stack and call location by following a few examples.
We define three functions
f2 is called inside
f3 is called inside
f2, so the program will execute
f3() one after another, the call stack is f1 when executing f1, when executing
f2, the call stack is
f2, when executing
f3, the call stack is
f1 --> f2 --> f3, so the call stack is similar to a single chain table, from the head of the table to the end of the table in order of execution.
Some debugging tools have a special call stack panel that shows the call stack of the current program execution. In Google Chrome, you can press
F12 to open Developer Tools and switch to the
Sources page, you can see the
call stack panel, which will show the call stack when the program is executed.
Below, I have summarized four binding rules for
this. Before applying the following rules, you need to analyze the call stack to find where the function is called, and then judge to apply one of the four rules below.
This is the default rule for
this binding, which is used when no other rule can be applied.
var a = 2 is equivalent to
window.a = 2.
When using default binding,
this is bound to the global object. In the above example, when the function
f() is executed,
this is default bound to the global object, i.e.,
this is pointing to the global object, so the output is 2.
Note that when the program is declared
"use strict", the global object cannot be used for default binding.
Note: Try to use strict patterns in your code, non-strict patterns tend to write code that is difficult to maintain. And don’t use a mix of strict and non-strict patterns.
When a function is executed, it belongs to some object Object, then
this is bound to that object at that time.
Although the function
f is defined in the global scope, it is added to obj as a reference, and when
obj.f() is executed,
f ‘belongs’ to
obj, so the output is 3.
Change the above example a bit.
At this point, the output is 2. Why? Because strictly speaking functions do not belong to any one object, the
f in the above example are just a reference to a function, so
obj.f are not directly related, just the same function referenced, so the execution of
f(), at this time the execution environment in the global scope, will automatically apply the default binding rules to bind
this to the global object. The second example, a more common this binding problem, is called implicit loss of this .
The problem of implicit loss is often encountered in callback functions.
f2(obj.f), you actually try to assign
f1 to the argument
f2, which is actually just a reference to the function, so the result is
The bind this value can be displayed with the
call method, the display specifies that this is bound to the
obj object, and the output is 2. Multiple arguments can be passed to
call, with the first argument specifying the
this binding object and the subsequent arguments specifying the arguments needed to execute the function.
apply method is similar to
call, except that the
call method takes a list of arguments, while the
apply method takes an array of multiple arguments.
bind method creates a new function, and when
bind is called,
this of this new function is specified as the first argument of
bind, and the rest of the arguments will be used as arguments of the new function for the call.
new keyword, because there are no actual
operator, they do not belong to a class, nor do they instantiate a class, they are just ordinary functions that are called by thenew` operator.
Calling a function (constructor) with
new will automatically perform the following steps.
- Create a new empty object as an instance of the object to be returned.
- Prototype the empty object to the function’s
- Bind the empty object to the
thiskeyword inside the function.
- Execute the code inside the function (usually by assigning a value to the this attribute and initializing the object).
The third step above, is the new binding.
After describing the four binding rules, the next step is to describe the complete steps to determine the priority of each method.
- new binding, if the function is called in
thisis bound to the newly created object.
- display binding, if the function is called in
thisbinds to the specified object.
- implicit binding, if the function is called in some context object, if yes, then
thisis bound to that context object. 4.
- If none of the above, the default binding is used, which is
undefinedin strict mode and the global object in non-strict mode.
There are always exceptions to everything, and here is one of the more common exceptions - the arrow function
Instead of using the four binding rules of
this, arrow functions determine who to bind
this to based on the outer (function or global) scope.
Why is the this of the above
myMethod() execution a global object? Because the this of an arrow function inherits from its outer (function or global) scope.
Continue with an example.