I’ve received several explanations of the idea of “hoisting” with several of them being wrong. Some people think it has to do with closures, or is just a synonym for function scoping. Here’s my ultra-short version of hoisting as I understand it.
Hoisting involves the interplay of just a few concepts:
As an implementation detail of function scoping, all variable declarations are “hoisted” to the top of their scope.
Variable assignments are not hoisted.
Named function declarations are considered variable declarations.
The trivial upshot of this is that if you declare
var x = 1; in the middle of a function, it’ll actually be run as if there was a
var x; at the top of the enclosing function, and a
x = 1; where you wrote it.
The same thing goes for inner functions you define except that, as I mentioned, named function declarations are considered variable declarations, not assignments. Here’s the fastest way to see how that works out:
The first example,
noBar works pretty much as you’d expect: it throws an error because there’s a problem trying to invoke
bar(). But notice the error:
bar is not defined.
The second example
hoistedVar, works similarly but throws a different error! This is because the definition
var bar has been quietly hoisted to the top of the function (above the
console.log call). So
bar exists, but has not been assigned to yet. Its current value is undefined. See bullet points 2 and 3.
The last example works, somewhat unexpectedly. However, if you realize that named functions are considered variable declarations (see point 4) you’ll be able to see that the whole definition has been hoisted to the top of the function (again, above the
So that’s what hoisting means. It is left as an exercise for the reader to figure out how this affects the well-intentioned late variable declaration you may do and why that code that you didn’t think should’ve worked actually worked that one time.