In JavaScript, when using a function expression (e.g. var myFunc = function() {...}
), like any other variable declaration, you have to define the variable before using it. For example, the following example will not work (will result in Uncaught TypeError: myFunc is not a function
):
var myVar = myFunc();
var myFunc = function() {
// code here...
}
However, in my routes/index.js file of a node js project, I have the following code (abbreviated obviously):
var router = express.Router();
.
.
.
router.post('/', function(req, res) {
...
...
var myVar = myFunc(); // WORKS!
...
...
}
var myFunc = function() {
...
}
The myFunc
variable is declared after it is used, so shouldn't this throw an error?
There are two aspects to this:
Why can the callback passed to
router.post
access themyFunc
variable, when the variable declaration is below it in the code?Why can the callback passed to
router.post
access the function assigned to themyFunc
variable, when it's not assigned to the variable until below it in the code?First we'll deal with the variable, then we'll deal with its value (the function we assign to it):
It would if
var
weren't hoisted. Butvar
is hoisted. So when your module is loaded, first the JavaScript engine looks through it to find all variable declarations and function declarations, processes those, and then does the step-by-step code in your module.E.g., to the JavaScript engine, your module actually looks like this:
More on this on my anemic little blog: Poor misunderstood
var
It does. The only reason you're not running into trouble is that
myFunc
isn't used until the callback you're passing intorouter.post
is called, which is after the top-level scope code of your module script has been run (including the expression creatingmyFunc
).E.g., what happens is:
The prep stuff (creating the vars
router
andmyFunc
and setting them toundefined
)The
express.Router
call, which assigns a new value torouter
The call to
router.post
, passing in but not calling a callback functionCreation of the function, which assigns a new value to
myFunc
Later, when a request comes in, the callback is called, by which time
myFunc
has been created (and is accessible because the callback is a closure over the context wheremyFunc
is declared)This is analogous to this:
First
setTimeout
is called, then the function is created and assigned tomyFunc
, then later the callback function is called and calls the function viamyFunc
.