This problem has actually plagued me for a long time. Now I finally want to understand it. I 'd like to share it with you. If there is something wrong, please correct it. I will come back to fix it at any time.
1. Confused! Doubts caused by a piece of code
See the following code:
The Code is 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 result:
Undefined, undefined
3, 3
3, 3
3
If you are using c, java, and other languages, you may not be able to understand why local variables such as j and k can be accessed by code outside the scope?
If a variable declared with var in JavaScript can be regarded as a local variable, the scope that can access this variable is the local scope of this variable. For example, in the console. log line, the j and k scopes are still available, while the I scopes are still available outside the loop. Speaking of this, maybe I can say that JavaScript has no truly meaningful local scope. Really? None!
2. How to obtain a real local scope? A writing method caught my attention.
You may have read JQuery's source code or Ext's source code and may be familiar with the following method.
The Code is 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 result:
3, 4
1, 2
It is amazing to find that (in fact, it is not amazing, as we all know) The function has an independent scope, that is, the variable declared by the var inside the function, which can be used only within the function. Therefore, masters of various frameworks write this statement to prevent conflicts between local variables and external variables (outer local variables and global variables.
So far, I took back the arbitrary inference in the first article and modified it:
JavaScript is bounded by functions. Each function has a local scope. Any other block (including common code blocks, for loops, if, while, and other code blocks) does not have a local scope, variables declared using var can directly pass through these code blocks and can be accessed by external code.
3. When is an error reported and when is it undefined? Var declaration mechanism
Check the Code:
The Code is as follows:
Console. log ()
Output result:
ReferenceError: a is not defined
Output result:
Undefined
The Code is as follows:
Var exports = (function (){
Var a = 1, B = 2;
Return {a: a, B: B };
})();
Console. log ();
Output result:
ReferenceError: a is not defined
Conjecture conclusion:
Each time the JavaScript engine executes the code, it first scans all the code in the scope (the code inside the function in the scope is not scanned) and records all the variables declared by var, before the code is executed to assign values, the values of these variables are undefined. After that, if you access the local variable first, if you do not have this local variable, you will access the local variable on the previous layer (for example, the closure and the previous layer create the closure environment ), until you access the full local variable. If no such variable exists, an exception is thrown.
4. digression: Closure + Asynchronization, variable value disorder! How can we ensure that the current value of a local variable is passed asynchronously?
Or code:
The Code is as follows:
For (var I = 0; I <3; I ++ ){
SetTimeout (function (){
Console. log (I );
}, 1 );
}
Output result:
3
3
3
Why? When the closure is executed asynchronously, I always accesses the I of the outer scope. Because of the Asynchronization, the loop has ended when the closure is executed, and I is 3, therefore, each print is 3.
So how can we solve this problem? We need to convert I to a local variable.
Well, some people may write this way:
The Code is as follows:
For (var I = 0; I <3; I ++ ){
Var j = I;
SetTimeout (function (){
Console. log (j );
}, 1 );
}
Output result:
2
2
2
Why?
As I have explained before, j and I have the same scope. All are outer local variables. When the loop execution is completed asynchronously, j is 2 (I ++ is less than I );
What should we do? (Imagine an advertisement, (⊙ v ⊙ )).
As you know, the parameters in the function are also the local variables of the function. There is a way to convert a local variable to a real parameter of the function, so as to pass the value.
The Code is as follows:
For (var I = 0; I <3; I ++ ){
SetTimeout ((
Function (j ){
Return function (){
Console. log (j );
}
}) (I)
, 1 );
}
Output
0
1
2
As a matter of fact, everyone can understand the code as soon as it is written. This anonymous function is used to remove the problem of variable changes in asynchronous mode, but this post is a topic.
Summary:
Amount. No, I'm lazy. I will try again later. Hey.
In fact, all these conclusions should be written in RFC. But the English document... Forget it .. I inferred it myself. Haha.