Being too wedded to the literal meaning of "this" will create some misunderstanding. There are two common explanations for this, but they are all wrong.
Explain what the dynamic scope is before the introduction
Briefly analyze the dynamic scope and reiterate its differences from lexical scopes. But actually the dynamic scope is another important mechanism of JavaScript this cousin. Lexical scopes are a set of rules about how the engine looks for variables and where to find variables. The most important feature of lexical scopes is that its definition process occurs in the writing phase of the code (assuming you are not using eval () or with). The dynamic scope seems to imply that there are good reasons to make the scope as a form of dynamic determination at run time, rather than static determination when writing code, in fact. Use the sample code to illustrate:
650) this.width=650; "src="/img/fz.gif "alt=" Copy Code "style=" Margin:0px;padding:0px;border:none; "/>
function foo () {console.log (a);//2}function bar () {var a = 3;foo ();} var a = 2;bar ();
650) this.width=650; "src="/img/fz.gif "alt=" Copy Code "style=" Margin:0px;padding:0px;border:none; "/>
The lexical scope allows a in Foo () to be referenced to a in the global scope by RHS (a form of assignment in JS), thus outputting 2. Dynamic scopes do not care about how functions and scopes are declared and where they are declared, only about where they are called from. In other words, the scope chain is based on the call stack, not the scope nesting in the code. Therefore, if JavaScript has a dynamic scope, in theory, foo () in the code below will output 3 at execution time.
650) this.width=650; "src="/img/fz.gif "alt=" Copy Code "style=" Margin:0px;padding:0px;border:none; "/>
function foo () {console.log (a);//3 (not 2!) )}function Bar () {var a = 3;foo ();} var a = 2;bar ();
650) this.width=650; "src="/img/fz.gif "alt=" Copy Code "style=" Margin:0px;padding:0px;border:none; "/>
Why is that? Because when Foo () cannot find a variable reference, it looks for a in the call stack where foo () is called, instead of looking up in the nested lexical scope chain. Because Foo () is called in Bar (),
The engine checks the scope of bar () and finds a variable A with a value of 3. That's weird, isn't it? Now you might think so. But this is because you may have written only lexical-scoped code (or at least a lexical scope-based
In-depth thinking), so they are unfamiliar with dynamic scopes. If you write code only in a dynamic-scoped language, you'll feel it's natural, and the lexical scopes look weird. It is important to be clear that JavaScript does not actually have dynamic scopes. It is only lexical scope, simple and clear. But the this mechanism is somewhat like a dynamic scope.
The main difference: Lexical scopes are determined when writing code or definition, while dynamic scopes are determined at run time. (This is also!) The lexical scope focuses on where the function is declared, and the dynamic scope concerns where the function is called from.
Finally, this concerns how the function is called, which shows how tightly the relationship between this mechanism and the dynamic scope is.
The call stack in chrome can be viewed in debug mode (this is nonsense, of course).
650) this.width=650; "Src=" http://images2015.cnblogs.com/blog/1029816/201702/ 1029816-20170211145658885-1407631546.png "style=" margin:0px;padding:0px;border:0px; "/>
1. Point to itself
It is easy to interpret this as pointing to the function itself, which makes sense from the grammatical point of view of English. So why do you need to refer to the function itself from within the function? A common cause is recursion (calling this function from within a function) or writing an event handler that will unbind itself after the first call.
Novice JavaScript developers often think that since a function is considered an object (all functions in JavaScript are objects), it is possible to store the state (the value of the property) when the function is called. This is feasible and sometimes useful, but in many modes you will find that in addition to the function
Objects also have many places where storage states are more appropriate. But now let's analyze the pattern and let's see that this is not pointing to the function itself as we thought.
We want to record the number of times the function foo is called, and think about the following code:
650) this.width=650; "src="/img/fz.gif "alt=" Copy Code "style=" Margin:0px;padding:0px;border:none; "/>
1 function foo (num) {2 console.log ("foo:" + num); 3//Record Foo is called 4 this.count++; 5} 6 foo.count = 0; 7 var i; 8 for (i=0; i<10; i++) {9 if (i > 5) {ten foo (i);}12}13//foo:614//foo:715//foo:816//foo:917//foo How many times has it been called? Console.log (Foo.count); 0--WTF?
650) this.width=650; "src="/img/fz.gif "alt=" Copy Code "style=" Margin:0px;padding:0px;border:none; "/>
The Console.log statement produced 4 outputs, proving that Foo (..) was actually called 4 times, but Foo.count is still 0. Obviously it is wrong to understand this from the literal sense. Execution Foo.count = 0 o'clock, indeed a property count was added to the Function object foo. But the inner code of the function
This does not point to that function object in This.count, so the root object is not the same, although the property name is the same, and confusion arises. The responsible developer will certainly ask, "if I add the Count property to the expected difference, which count do I add?" "In fact, if he explores it, it will find that the code
A global variable count was inadvertently created (see Chapter 2nd), which has a value of Nan. Of course, if he finds out about this strange result, then he will continue to ask, "Why is it global, and why is its value a nan instead of a more appropriate value?" (see Chapter 2nd.) )
When confronted with such a problem, many developers do not think deeply about why this behavior is inconsistent with expectations and will not attempt to answer questions that are difficult to solve but are very important. They only shy away from the problem and use other methods to achieve the goal, such as creating another object with the Count property.
650) this.width=650; "src="/img/fz.gif "alt=" Copy Code "style=" Margin:0px;padding:0px;border:none; "/>
function foo (num) {console.log ("foo:" + num);//record foo is called data.count++;} var data = {Count:0};var i;for (i=0; i<10; i++) {if (i > 5) {foo (i);}} How many times has foo:6//foo:7//foo:8//foo:9//foo been called? Console.log (Data.count); 4
650) this.width=650; "src="/img/fz.gif "alt=" Copy Code "style=" Margin:0px;padding:0px;border:none; "/>
In some ways this approach does "solve" the problem, but unfortunately it ignores the real problem-the meaning of this and how it works-but returns to the comfort zone, using a more familiar technique: lexical scopes. Lexical scopes are a very good and useful technique. I didn't mean to belittle it (but
To refer to the first part of this book, "Scopes and closures"). But if you are simply unable to guess the use of this, it is not a good solution to give up learning this and go to the lexical scope. If you are referencing itself from within a function object, it is not sufficient to use this only. Generally you need to pass a finger
Reference it to the lexical identifier (variable) of the Function object.
Consider the following two functions:
function foo () {foo.count = 4;//Foo points to itself}settimeout () {//Anonymous (no-name) functions cannot point to itself}, 10);
The first function is called a named function, and within it you can use Foo to refer to itself. In the second example, however, the callback function passed into the settimeout (..) does not have a name identifier (this function is called
anonymous function), you cannot reference itself from within the function. There is a traditional but now deprecated and critical usage, which is to use Arguments.callee to refer to the currently running function object. This is the only method that can reference itself from within an anonymous function object. However, a better approach would be to avoid using anonymous functions, at least by using a named function (an expression) when self-referencing is required. Arguments.callee has been deprecated and should not be used again.
So, for our example, another workaround is to use the Foo identifier instead of this to refer to the function
Object:
650) this.width=650; "src="/img/fz.gif "alt=" Copy Code "style=" Margin:0px;padding:0px;border:none; "/>
function foo (num) {console.log ("foo:" + num);//record foo is called foo.count++;} Foo.count=0var i;for (i=0; i<10; i++) {if (i > 5) {foo (i);}} About this | How many times has 79//foo:6//foo:7//foo:8//foo:9//foo been called? Console.log (Foo.count); 4
650) this.width=650; "src="/img/fz.gif "alt=" Copy Code "style=" Margin:0px;padding:0px;border:none; "/>
However, this approach also avoids the problem of this and relies entirely on the lexical scope of the variable foo.
Another way is to force this to point to the Foo function object:
650) this.width=650; "src="/img/fz.gif "alt=" Copy Code "style=" Margin:0px;padding:0px;border:none; "/>
function foo (num) {console.log ("foo:" + num),///Note that the number of times Foo is called//attention, in the current invocation mode (see code below), this does point to foothis.count++;} Foo.count = 0;var i;for (i=0; i<10; i++) {if (i > 5) {//Use call (..) to ensure that this pointer to the function object Foo itself foo.call (foo, i);}} How many times has foo:6//foo:7//foo:8//foo:9//foo been called? Console.log (Foo.count); 4
650) this.width=650; "src="/img/fz.gif "alt=" Copy Code "style=" Margin:0px;padding:0px;border:none; "/>
This time we accepted this and did not shy away from it.
2 its scope
The second common misconception is that this refers to the scope of the function. The problem is a bit complicated, because in some cases it is correct, but in other cases it is wrong. It is important to be clear that this does not point to the lexical scope of the function in any case. Inside JavaScript, scopes are really like objects, and the visible identifier is its property. But the scope "object" cannot be accessed through JavaScript code, it exists inside the JavaScript engine.
Consider the following code, which attempts (but does not succeed) to cross the boundary, using this to implicitly refer to the lexical scope of the function:
650) this.width=650; "src="/img/fz.gif "alt=" Copy Code "style=" Margin:0px;padding:0px;border:none; "/>
function foo () {var a = 2;this.bar ();} function Bar () {console.log (THIS.A);} Foo (); REFERENCEERROR:A is not defined
650) this.width=650; "src="/img/fz.gif "alt=" Copy Code "style=" Margin:0px;padding:0px;border:none; "/>
There are more than one error in this piece of code. While this code may seem like an example of what we deliberately write, it actually comes from the Code of Excellence in a mutual help forum in a public community. This piece of code is perfect (and also sad)
Show how easy it is to mislead people. First, this code attempts to refer to the bar () function through This.bar (). It is absolutely impossible to succeed, and we will explain why later. The most natural way to call bar () is to omit the preceding this and use the lexical reference identifier directly. In addition, the developer who wrote this code also tried to use this link to the lexical scope of Foo () and bar (), allowing bar () to access variable A in the Foo () scope. This is not possible, and you cannot use this to refer to something inside a lexical scope. Whenever you want to mix this with lexical scopes, be sure to remind yourself that this is not possible.
This acts like a dynamic scope, and the dynamic scope does not care about how functions and scopes are declared and where they are declared, only about where they are called from. In other words, the scope chain is based on the call stack, not the scope nesting in the code.
Some misconceptions about JavaScript this