Execution Environment, scope, and hoisting in JavaScript)
Let's take a look at the following code:
var a = 0;alert("1st alert : a = " + a);function fun(){ alert("2nd alert : a = " + a); var a = 1; setTimeout(function(){ alert("3rd alert : a = " + a); a = 2; },1000); a = 3; setTimeout(function(){ alert("4th alert : a = " + a); a = 4; },4000);}fun();alert("5th alert : a = " + a);
The result of code execution is:
1st alert: a = 0
2nd alert: a = undefined
5th alert: a = 0
3rd alert: a = 3
4th alert: a = 2
Question 1: Why is the value of a undefined for 2nd alert?
First, let's look at the JS execution environment and scope.
The executing context defines other data that a variable or function has access. In JS, there are two execution environments: one is the global environment, that is, the window object in the Web browser, and the other is the function execution environment.
There is a variable object in the execution environment, which saves all the variables and functions defined in the environment.
When the code is executed, a scope chain of the variable object is created. The frontend of the scope chain is the variable object of the current environment, and then the variable object of the outer environment in turn, layer by layer until the global execution environment.
During the identifier parsing process, the first-level search will start from the front end along the scope chain until the identifier is found or the entire local search environment is found.
Therefore, curly braces in JS do not represent an independent scope. variables defined in the circular body can still be accessed in vitro (in the same execution environment)
Take the following example:
var a = 0;function fun(){ alert("a=" + a);}fun();
The result is a = 0.
This is because when the fun function is called, the search identifier a cannot be found in the current execution environment, but a is found when the outer scope is searched through the scope chain.
In the first example, why is the value of 2nd alert and a undefined?
This is because in JS, variables declared using var or functions declared using function declaration (not function expressions) are automatically added to the nearest environment, that is, hoisting ). What does it mean? The first two lines of code in the preceding fun function definition become:
function fun(){ var a; alert("2nd alert : a = " + a); a = 1; //other codes}
Therefore, you can search for identifier a in the current execution environment, instead of the outer environment. Therefore, in 2nd alert, the value of a is undefined.
This is also the definition of the function, which is why the function can be called before the function declaration when using the function declaration method, but the function expression cannot be used.
Question 2: Why is 5th alert before 3rd and 4th?
This is because the JavaScript engine processes the task queue in a single thread, while setTimeout is an asynchronous code. asynchronous code is executed only when no code is synchronized in the JS thread.
setTimeout(function(){while(true){}},1000);setTimeout(function(){alert('end 2');},2000);setTimeout(function(){alert('end 1');},100);alert('end');Therefore, in the above Code, the first appearance is end, and the second is end 1, and then it will not appear again. In the first setTimeout function, the infinite loop occupies the single thread of the JS engine and blocks other processes.