Forgive me if this is the wrong way to approach adding a point. I haven't been around here all the much, and would welcome constructive direction and/or criticism.
Benjamin's answer addresses the OP's question excellently, but I'd like to add one tweak that'll give us a full tour of hoisting and its oddities.
If we begin the original code with a call to f
, like so:
f();
var f = function() {
console.log("Me original.");
};
function f() {
console.log("Me duplicate.");
}
f();
The output will then be:
Me duplicate.
Me original.
The reason being that var
and function
statements are hoisted in slightly different ways.
For var
the declaration is moved to the top of the current scope*, but any assignment is not hoisted. As far as the value of the declared var goes, it's undefined until the original assignment line is reached.
For function
statements, both the declaration and definition are hoisted. Function expressions, as used in the var f = function() {...
construct, are not hoisted.
So after hoisting, execution is as if the code were:
var f; // declares var f, but does not assign it.
// name and define function f, shadowing the variable
function f() {
console.log("Me duplicate.");
}
// call the currently defined function f
f();
// assigns the result of a function expression to the var f,
// which shadows the hoisted function definition once past this point lexically
f = function() {
console.log("Me original.");
}
// calls the function referenced by the var f
f();
*All JavaScript scope is lexical, or function, scope, but it seemed like it would just confuse things to use the f word at that point.