Let's look at the following code:
1 varA = 0;2Alert ("1st alert:a =" +a);3 functionFun () {4Alert ("2nd alert:a =" +a);5 varA = 1;6SetTimeout (function(){7Alert ("3rd alert:a =" +a);8A = 2;9},1000);TenA = 3; OneSetTimeout (function(){ AAlert ("4th alert:a =" +a); -A = 4; -},4000); the } - Fun (); -Alert ("5th alert:a =" + a);
The result of the code execution is:
1st alert:a = 0= = 0= 3= 2
Question 1: For 2nd alert, why is the value of a undefined?
First, we look at the execution environment and scope of JS.
The execution environment (executing context) defines additional data that a variable or function has access to. In JS, there are two kinds of execution environment, one is the global environment, that is, the Window object in the Web browser, and the other is the execution environment of the function.
There is a variable object in the execution environment that holds all the variables and functions defined in the environment.
When the code executes, it creates a scope chain for the variable object, the front end of the scope chain is the variable object of the current environment, and then the variable object of the outer environment, one by one, to the global execution environment.
During the parsing of identifiers, searches are initiated from the front end along the scope chain, until an identifier is found or a full office environment is searched.
So in JS, the curly braces do not represent a separate scope, the variables defined in the loop body, and can still be accessed (in the same execution environment) outside the loop body.
Look at the following example:
1 var a = 0; 2 function Fun () {3 alert ("a=" + a); 4 }5 fun ();
The result is a=0.
This is because the search identifier A is not found in the execution environment when the fun function is called, but a is found when the scope chain is searched for the outer scope.
And why the first example, 2nd alert, the value of a is undefined?
This is because in JS, a variable declared with Var or a function declared using a function declaration (not a function expression) is automatically added to the closest environment, the so-called variable elevation (hoisting). What do you mean, the code that corresponds to the first two lines of the above fun function definition becomes:
1 function Fun () {2 var A; 3 Alert ("2nd alert:a =" + a); 4 A = 1; 5 // Other codes 6 }
So when searching for identifier A, you can search in this execution environment without searching the outer environment, so in 2nd alert, the value of a is undefined.
The same is true for the definition of a function, which is why the calling function can be placed before the function declaration, but not when the function expression is used.
Question 2:5th alert why before 3rd and 4th?
This is because the JavaScript engine is single-threaded for its task queue, and SetTimeout is an asynchronous code that executes asynchronously only when there is no synchronization code in the JS thread.
1 setTimeout (function() {while (true) {}},1000); 2 setTimeout (function() {alert (' End 2 ');},2000); 3 setTimeout (function() {alert (' End 1 ');},100); 4 alert (' End ');
So in the above code, the first thing that appears is end, followed by end 1, and never again. Because the dead loop in the first setTimeout function takes up a single thread of the JS engine, it blocks other processes.
A common use of settimeout is to have a method defer execution. We know that the SetTimeout method is hung under the Window object. The code for the timeout call is executed in the global scope, so the value of this in the function points to the window object in non-strict mode, which is undefined in strict mode
Automatic semicolon Insertion
Although JavaScript has a code style of C, it does not force the use of semicolons in your code, and you can actually omit them.
JavaScript is not a language without semicolons, and on the contrary it requires a semicolon to parse the source code. Therefore, the JavaScript parser automatically inserts a semicolon in the source code when it encounters a parsing error caused by a missing semicolon.
var=function(){
}//Parse error, semicolon missing
Test()
A semicolon is automatically inserted and the parser is re-parsed.
var=function(){
}; //No error, parsing continues
Test()
Automatic semicolon insertion is considered one of the biggest design flaws in the JavaScript language because it can change the behavior of the code.
Working principle (how it works)
The following code does not have a semicolon, so the parser needs to decide where to insert the semicolon.
(function(Window, Undefined) {
functionTest(Options) {
Log(' testing! ')
(Options.List|| []).Foreach(function(I) {
})
Options.Value.Test(
' Long string to pass here ',
' and another long string to pass '
)
Return
{
Foo: function() {}
}
}
Window.< Span class= "PLN" >test = test
}) ( Window
(function (window) {
Window. Somelibrary = {}
}) (window)
The following is the result of the parser "guessing".
(function(Window, Undefined) {
functionTest(Options) {
Not inserted, Lines got merged
Log(' testing! ')(Options.List|| []).Foreach(function(I) {
}); <-inserting a semicolon
Options.Value.Test(
' Long string to pass here ',
' and another long string to pass '
); <-inserting a semicolon
Return; <-inserts a semicolon, changing the behavior of the return expression
{ Processing as a code snippet
A label and a single expression statement
Foo: function() {}
}; <-inserting a semicolon
}
Window.test = Test;//<-insert semicolon
//the lines got merged Again
}) (windowfunction (window) {
Window. Somelibrary = {};//<-insert semicolon
}) (window //<-insert semicolon
Note: JavaScript does not correctly handle a return expression immediately following a newline character, although this is not an automatic semicolon insertion error, but this is an undesirable side effect.
The parser significantly alters the behavior of the above code and, in other cases, makes the wrong deal .
Front bracket (Leading parenthesis)
In the case of the front bracket, the parser does not automatically insert a semicolon.
Log(' testing! ' )
(options.| | []). ForEach(function(i){})
The above code is converted to a line by the parser.
Log(' testing! ' ) (options.| | []). ForEach(function(i){})
logThe result of a function's execution is probably not a function; In this case TypeError , the error will occur, and the detailed error message may be undefined is not a function .
conclusion (In conclusion)
It is recommended that you never omit semicolons, but also that you put curly braces and corresponding expressions on one line, and that if else you should not omit curly braces for a single line of code or an expression. These good programming habits not only refer to the consistency of the code, but also prevent the parser from changing the error handling of code behavior.
JS scope, variable elevation