The idea of "hoisting" is a bad way to understand what's going on. In other words, in my opinion "hoisting" is a bad explanation for hoisting.
What's really going on is not "hoisting". What's really going on is that javascript executes code in two phases: the compile phase and the eval phase. The javascript community calls the symptom of this "hoisting" but most people fail to understand why hoisting hoists because they think javascript interpreters have this feature called "hoisting" (they don't).
What actually happens is simpler to explain than the idea of hoisting. The rules are:
Javascript always parse code from the top-down. It never reorders code (it never hoists).
There are two phases of execution: compilation and evaluation.
All declarations are processed in the compilation phase, no expressions will be evaluated in the compilation phase (because "evaluating" things are done in the evaluation phase).
All expressions and anything else that need to be evaluated are processed in the evaluation phase.
Remember rule 1, all parsing are done top-down and there are no backtracking, no hoisting.
Let's take your example and try to understand it by keeping in mind javascript's compilation and evaluation phase:
var myName = "Richard"; // Variable assignment (initialization)
function myName () {
console.log ("Rich");
}
console.log(typeof myName); // string
In the compilation phase, the interpreter sees you declaring a variable. It allocates an area of memory for this variable and assigns it the value of undefined
.
In the compliation phase, the interpreter sees you declaring a function. It also notices that the function name shadows the variable name. So it creates a function "myName" (which means that at this point the variable myName
points to the function).
Compilation phase ends. Now we enter the evaluation phase.
In the evaluation phase, the interpreter sees you assigning a string to myName
.
There is nothing to evaluate when we reach the function declaration because declarations are processed in the compilation phase.
In the evaluation phase, the interpreter sees you console.logging the typeof myName
. Since the last thing assigned to it was a string it prints "string".
Note that if you remove the string assignment then myName
will be typeof "function". That's because in that case the last thing assigned to it is the declared function.
See this related question for other subtleties caused by the two phases of execution: JavaScript function declaration and evaluation order