JavaScript is a scripting language that supports advanced functions such as functional programming, closures, prototype-based inheritance, etc. JavaScript seems to be easy to get started at first, but as you use it in depth, it is actually difficult to master JavaScript, and some basic concepts are incredible. Among them, the keyword this in JavaScript is a relatively confusing concept. In different scenarios, this will become different objects. There is a view that only by correctly mastering this keyword in JavaScript can you enter the threshold of the JavaScript language. In mainstream object-oriented languages (such as Java, C#, etc.), this means clear and specific, that is, pointing to the current object. Generally bound during the compilation period. This is bound during the runtime in JavaScript, which is the essential reason why this keyword has multiple meanings in JavaScript.
Due to its binding feature during runtime, this in JavaScript can be a global object, a current object or any object, which depends entirely on the way the function is called. There are several ways to call functions in JavaScript:
Called as object method;
as a function call;
Called as a constructor;
Use apply or call to call.
As the saying goes, a character is not as good as a form, and a form is not as good as a picture. In order to make people better understand what JavaScript this points to? Here is a picture to explain:
In the picture above, I call it "JavaScript this decision tree" (in non-strict mode). The following is an example to illustrate how this figure can help us judge this:
var point = { x: 0, y: 0, moveTo: function(x, y) { this.x = this.x + x; this.y = this.y + y; }};// Decision tree explanation: The point.moveTo(1,1) function is not called for new, enters the veto, // It is called with dot(.), and then points to the call object before .moveTo, that is, pointpoint.moveTo(1,1); // this is bound to the current object, that is, point objectIs the point.moveTo function call called with new? This is obviously not. Going into the "No" branch, that is, is the function called with dot(.)? ;
The point.moveTo function is called with dot(.), that is, it enters the "yes" branch, that is, this here points to the object point before point.moveTo.
The analysis diagram of what this point to in the figure point.moveTo function is shown in the following figure:
Let’s give another example, look at the following code:
function func(x) { this.x = x; } func(5); // this is a global object window, x is a global variable//Decision tree analysis: Is the func() function called with new? To no, is it called with dot when entering the func() function? To no, this points to the global object windowx; // x => 5The process of determining the func() function in "JavaScript this decision tree" is as follows:
Is func(5) function call called with new? This is obviously not. Going into the "No" branch, that is, is the function called with dot(.)? ;
The func(5) function is not called with dot(.), that is, it enters the "No" branch, that is, this point to the global variable window, then this.x is actually window.x.
The analysis diagram of what this func function points to is shown in the following figure:
For the method of calling directly as a function, let’s see a complex example:
var point = { x: 0, y: 0, moveTo: function(x, y) { // Inner function var moveX = function(x) { this.x = x; // What does this point to? window }; // The internal function var moveY = function(y) { this.y = y; //What does this point to? window }; moveX(x); moveY(y); } }; point.moveTo(1,1); point.x; // =>0 point.y; // =>0 x; // =>1 y; // =>1The actual internal call of the moveX() and moveY() functions. The process of determining this inside the moveX() function in the "JavaScript this decision tree" is as follows:
Is the moveX(1) function call called with new? This is obviously not. Going into the "No" branch, that is, is the function called with dot(.)? ;
The moveX(1) function is not called with dot(.), that is, it enters the "No" branch, that is, this here points to the global variable window, then this.x is actually window.x.
Let's take a look at the example of a constructor call:
function Point(x,y) { this.x = x; // this ? this.y = y; // this ?}var np = new Point(1,1);np.x; // 1var p = Point(2,2);px; // error, p is an empty object undefinedwindow.x; // 2The process of determining this in the "JavaScript this decision tree" in the Point(1,1) function is as follows:
var np=new Is the Point(1,1) call called with new? This is obviously, entering the "yes" branch, that is, this points to np;
Then this.x=1, that is, np.x=1;
The process of determining this in the "JavaScript this decision tree" in the Point(2,2) function in var p=Point(2,2) is as follows:
Is the var p= Point(2,2) call called with new? This is obviously not. Going into the "No" branch, that is, is the function called with dot(.)? ;
Is the Point(2,2) function not called with dot(.)? Determined as No, that is, enter the "No" branch, that is, this here points to the global variable window, then this.x is actually window.x;
This.x=2 means window.x=2.
Finally, let’s take a look at the example of calling functions with call and apply:
function Point(x, y) { this.x = x; this.y = y; this.moveTo = function(x, y) { this.x = x; this.y = y; } } var p1 = new Point(0, 0);var p2 = {x: 0, y: 0};p1.moveTo.apply(p2, [10, 10]); // apply is actually p2.moveTo(10, 10)p2.x // 10The process of determining the function p1.moveTo.apply(p2,[10,10]) in the "JavaScript this decision tree" is as follows:
We know that the two methods apply and call are extremely powerful, and they allow switching the context of the function execution, that is, the object bound to this. p1.moveTo.apply(p2,[10,10]) is actually p2.moveTo(10,10). Then p2.moveTo(10,10) can be interpreted as:
Is the function call called with new? This is obviously not. Going into the "No" branch, that is, is the function called with dot(.)? ;
The p2.moveTo(10,10) function is called with dot(.), that is, it enters the "yes" branch, that is, this here points to the object p2 in p2.moveTo(10,10). before, so p2.x=10.
Regarding the process of JavaScript function execution environment, a description in the IBM developerworks document library feels very good, and the excerpt is as follows:
"Functions in JavaScript can be executed as ordinary functions or as objects, which is the main reason why this is so rich. When a function is executed, an execution environment (ExecutionContext) is created, and all the behaviors of the function occur in this execution environment. When building the execution environment, JavaScript First, the arguments variable will be created, which contains the parameters passed in when calling the function. Next, create a scope chain. Then initialize the variable, first initialize the formal parameter table of the function, the value is the corresponding value in the arguments variable. If there is no corresponding value in the arguments variable, the formal parameter is initialized as undefined. If the function contains internal functions, the internal functions will be initialized. If not, continue to initialize the local variables defined in the function. It should be noted that at this time, these variables are initialized as undefined, and their assignment operation will only be executed when the function is executed after the execution environment (ExecutionContext) is successfully created. This is for us to understand JavaScript The scope of variables in this is very important. Given the space, we will not discuss this topic here. Finally, assign values to this variable, as mentioned above, assign them to this global object, current object, etc. according to the different function call methods. At this point, the execution environment of the function (ExecutionContext) is successfully created, and the function begins to execute line by line, and the required variables are read from the execution environment (ExecutionContext) that was built before. "
Understanding this passage will be of great benefit to understanding Javascript functions.