In node.js, you need to be careful when you export functions out of a module using the module.exports =
style of export.
Try re-creating the two files a.js
and b.js
on your computer now, and then run node a
. You should see an error like
the following:
b.js:4
a()
^
TypeError: Property 'a' of object #<Object> is not a function
at module.exports (b.js:4:5)
at Object.<anonymous> (a.js:7:1)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:901:3
How does this happen? Let's walk the steps.
Node loads module a
because you specified loading it on the command-line. Internally, node creates a new empty object {}
for the exports for the object; this object will actually be the value of the exports
variable when module a
is run.
The first thing module a
does is load module b
. So, let's move to module b
.
Again, node will create a new empty object {}
for the exports for the module. The first thing module b
does is to require
module a
. Node is actually still in the process of loading module a
- it hasn't finished - but it did already create
the exports for module a
, and so it returns them. At this point, the variable a
in module b
will be set to the new
empty object {}. When a
is invoked in the exported function below this, the error will result.
You can see in module a
that it's supposed to be exporting a function. The problem is that this isn't done before
module b
does a require()
on a
, so b will end up getting access to the empty module export initially set for a
.
Patrick, I've also seen module.exports = { foo:.. bar:.. } instead of exports.foo = exports.bar =. I think the same issue will apply? Basically, don't override the exports object is the lesson here, I think?