JavaScript makes two passes. During first pass, js gathers all variable declarations (NOT assignments) and function definitions. In the second pass, js executes the code taking information learned in the first pass into consideration.
Code example
(function()
{
console.clear();
var i = 100;
console.log("S1.1 topmost: i = " + i);
function doIt1() {
// NO other variable with name i is declared in this function
// therefore, i refers to i declared in the enclosing function
console.log("S2.1 doIt1: i = " + i);
// this corresponds to function scope
// no var named i declared in this function
// this has function scope
console.log("S2.2 doIt1 (using this): i = " + this.i);
// NOTE: var keyword is NOT used
// changes value of i declared in enclosing function
i = 400; // changes value of i defined in enclosing function
console.log("S2.3 doIt1: i = " + i);
}
function doIt2() {
// i is the var defined below (equals undefined so far)
// i is NOT the i declared in enclosing function
console.log("S.3.1 doIt2: i = " + i);
// this refers to i defined in this function
console.log("S.3.2 doIt2 (using this): i = " + this.i);
// i is declared in this function scope
// NOTE the use of var keyword
// hides i declared in the enclosing function
// i is hoisted to the top of this function
// at the top of this function, i has value of undefined
// now assign it a value
do{
// i is declared at function scope
// even though it is within the curly braces of while
var i = 500;
} while(false);
// value is assigned to the local i
console.log("S1.2 doIt2: i = " + i);
}
doIt1();
doIt2();
// i retains the value assigned in doIt1
console.log("S1.3 topmost: i = " + i);
console.log("this.xxx limits scope to the current function's curly braces!")
}
)();
Output
S1.1 topmost: i = 100S2.1 doIt1: i = 100
S2.2 doIt1 (using this): i = undefined
S2.3 doIt1: i = 400
S.3.1 doIt2: i = undefined
S.3.2 doIt2 (using this): i = undefined
S1.2 doIt2: i = 500
S1.3 topmost: i = 400
this.xxx limits scope to the current function's curly braces!