14

I have the following redacted code:

module.exports = {
  read: read,
  write: write,
};

var read = function(parameters, config, next) {
  /* <snip> */
};

var write = function(parameters, config, next) {
  /* <snip> */
};

If I go to require() this file elsewhere, it will crash node and say that the required object has no method read or write. Wouldn't variable hoisting pull the functions above the modules.export = { ... };?

Scott
  • 6,716
  • 9
  • 40
  • 46

1 Answers1

21

It's the syntax you use to declare functions that matters due to function hoisting. If you declare those functions like this, they will get "hoisted" up in the scope and all is well.

module.exports = {
  read: read,
  write: write,
};

function read(parameters, config, next) {
  /* <snip> */
};

function write(parameters, config, next) {
  /* <snip> */
};

Side note: Named functions like in my snippet, as opposed to anonymous functions assigned to variables like in your snippet, are easier to debug and profile because their name gets included in stack traces.

Peter Lyons
  • 142,938
  • 30
  • 279
  • 274
  • Why would a variable not get hoisted above the `module.exports` assignments? Is `module` some special node object that gets declared and hoisted before any other code in the file is rendered? – Scott May 21 '14 at 19:34
  • 2
    Variables don't get hoisted. Just named functions declared without "var". – Peter Lyons May 21 '14 at 19:35
  • 4
    Ahhh, went back and re-read your linked article. The declaration of the variable is hoisted, but the value (in my case a function) is not assigned until later, whereas a named function will get hoisted along with its logic. Gotchya. – Scott May 21 '14 at 19:42
  • 4
    Just to expand on your side note, you can "name" anonymous functions assigned to variables and get the same benefits in your stack trace while debugging :) `var someFunc = function someFunc() { //... };`. A little repetitive maybe but it helps so much when debugging. You can name any anonymous function, even ones you're passing in as an argument: `db.query('stuff', function queryCallback() { //... });` and it shows up as a named function when debugging :D – CatDadCode May 21 '14 at 21:45
  • 2
    @Chev I did not know you could name functions passed as arguments! Thank you! – TheRyan722 Jun 29 '20 at 00:10