One, Myth! The confusion caused by a piece of code
Please see the following code:
Copy Code code as follows:
for (Var i=0;i<3;i++) {
Console.log (j+ "," +k);
for (Var j=0;j<3;j++) {
var k = j+1;
}
}
Console.log (i);
Output results:
undefined,undefined
3,3
3,3
3
If you are engaged in C, Java and other languages, you may be puzzled, why J, k such local variables can be scoped to the code access it?
If the variable declared in JavaScript is visualized as a local variable, then the scope of the variable can be accessed by the local scope of the variable. As in the example above, there is still a scope for J and K at the Console.log line, and the scope of I is still outside the loop. Speaking of which, perhaps I can arbitrarily say that JavaScript has no real meaning in the local scope. Are you sure? Not too!
second, how to obtain the real local scope? One of the wording caught my attention.
You may have seen the jquery source code or ext source code, may be a bit familiar with the following wording.
Copy Code code as follows:
var a = 3,b=4;
var exports = (function () {
var a = 1,b=2;
return {A:A,B:B};
})();
Console.log ("+a+", "+b");
Console.log (exports.a+ "," +exports.b);
Output results:
3,4
1,2
It's a magical discovery (and it's not magical, as we all know) inside a function is an independent scope, that is, a variable within the function, Var declaration, that can only be used within a function. So all the masters of the framework write this, to prevent their own local variables and external variables (outer local variables and global variables) conflict.
At this point, I take back the arbitrary inference in the first article and revise it:
JavaScript is bounded by functions, with a local scope within each function; any other block (including normal code blocks, for loops, if, while blocks of code) does not have a local scope, and variables declared with VAR can be accessed directly through these blocks of code.
when to complain, when undefined? The declaration mechanism of VAR
Look at the code:
Copy Code code as follows:
Output results:
REFERENCEERROR:A is not defined
Output results:
Undefined
Copy Code code as follows:
var exports = (function () {
var a = 1,b=2;
return {A:A,B:B};
})();
Console.log (a);
Output results:
REFERENCEERROR:A is not defined
Conjecture conclusion:
Each time the JavaScript engine executes the code, it scans all the code in the scope (the code inside the scope does not scan) and records all the Var declaration variables, before the code executes to the assignment, and the values of the variables are undefined. After that, if you access a variable, you first access the local variable, and if you do not have the local variable, you can access the local variable on the upper level (for example, the closure, the upper layer to create the environment for the closure) until you access the full board variable. If you do not have this variable, throw an exception.
Four, digression: Closure + asynchronous, variable value disorder! How do I ensure that the current value of a local variable is passed in an asynchronous situation?
Or the code to speak:
Copy Code code as follows:
for (Var i=0;i<3;i++) {
settimeout (function () {
Console.log (i);
},1);
}
Output results:
3
3
3
Why? Because when the closure is executed asynchronously, I always access the outer scope of I, because of the asynchronous, so in the execution of the closure when the loop is over, I already 3, so every time print out is 3.
So how do you solve the problem? We need to convert I to local variables.
Well, someone would have written this:
Copy Code code as follows:
for (Var i=0;i<3;i++) {
var j = i;
settimeout (function () {
Console.log (j);
},1);
}
Output results:
2
2
2
Why?
In fact, it has been explained before, in fact, the scope of J and I are the same. is the outer part of the local variable, in the asynchronous case when the loop execution completes when J is 2 (less than I i++);
So what should we do? (Please imagine an advertisement, (⊙v⊙)).
As you know, the parameters in the function also calculate the local variables of the function. So here's a way to convert a local variable into a function argument so that the value is passed.
Copy Code code as follows:
for (Var i=0;i<3;i++) {
SetTimeout (
Function (j) {
return function () {
Console.log (j);
}
}) (i)
, 1);
}
Output
0
1
2
Actually said so much, the code to write out we almost understand it, use this kind of anonymous function in addition to the asynchronous case of variable changes, but this is the subject of the topic.
Summarize:
Amount Do not write, I lazy, which day to make up. Hey.
In fact, these conclusions should be written in the RfC. But gnawing English documents ... or forget it. I infer it. Haha, don't laugh at me