Order of hoisting in JavaScript
function g () {
var x;
function y () {};
var z;
}
I would like to know exactly what order the above code becomes when hoisted.
Theory 1: Order between var
s and function
s remains as-is:
function g () {
var x;
function y () {};
var z;
}
Theory 2: var
s come before function
s:
function g () {
var x;
var z;
function y () {};
}
Theory 3: function
s come before var
s:
function g () {
function y () {};
var x;
var z;
}
Which theory is correct?
Solution 1:
Functions are hoisted first, then variable declarations, per ECMAScript 5, section 10.5 which specifies how hoisting happens:
We first have step 5 handling function declarations:
For each FunctionDeclaration f in code, in source text order do...
Then step 8 handles var
declarations:
For each VariableDeclaration and VariableDeclarationNoIn d in code, in source text order do...
So, functions are given higher priority than var
statements, since the later var
statements cannot overwrite a previously-handled function declaration.
(Substep 8c enforces the condition "If varAlreadyDeclared is false, then [continue...]" so extant variable bindings are not overwritten.)
You can also see this experimentally:
function f(){}
var f;
console.log(f);
var g;
function g(){}
console.log(g);
Both log
calls show the function, not an undefined
value.
Solution 2:
Although the order was fixed by the specification, as the accepted answer points out, that order really is not that important.
-
var
declarations are hoisted, but not their initialisation (if there is one). Avar
declaration is without effect if the name is already taken by afunction
or othervar
declaration. -
function
definitions are hoisted -- not only declaring the name, but also their value, i.e. the function.
So the following two pieces of code:
(function () {
console.log(typeof a);
var a = 1;
function a() { }
})();
and:
(function () {
console.log(typeof a);
function a() { }
var a = 1;
})();
... translate to:
(function () {
function a() { }
var a;
console.log(typeof a);
a = 1;
})();
and respectively:
(function () {
var a;
function a() { }
console.log(typeof a);
a = 1;
})();
The latter two are the same thing really. If the engine processes the hoisted var
declaration first, then a
is first undefined
but then immediately overwritten as function. If on the other hand the function
definition is processed first, then the var
declaration has no effect. In both scenarios the outcome is the same.