The function below is copied verbatim from Ch. 10 of Eloquent Javascript, and it runs perfectly with the v8 interpreter. However, it bombs out in Node with the object weekDay undefined. It also runs fine in the sandbox interpreter provided by the book. Can someone explain what's up?
(function(exports) {
var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"];
exports.name = function(number) {
return names[number];
};
exports.number = function(name) {
return names.indexOf(name);
};
})(this.weekDay = {});
console.log(weekDay.name(weekDay.number("Saturday")));
It's because this
in a Node module isn't pointing to the global object. It points to the exports
of that module. This means weekDay
isn't available as a global variable.
// ---------v
console.log(exports.weekDay.name(weekDay.number("Saturday")));
or
// ---------v
console.log(this.weekDay.name(weekDay.number("Saturday")));
To get a broad (and simplified) view of what a node module looks like, it basically takes your code and puts it in an IIFE.
So if this is your module...
this.foo = "bar"
console.log(exports.foo); // "bar"
it works because it's actually something like this...
var exports = {}; // Generated by Node
(function(exports) { // Generated by Node
this.foo = "bar"
console.log(exports.foo); // "bar"
}).call(exports, exports); // Generated by Node
Where the extra lines of code are generated by Node. You can see that it creates an object which it uses as both the this
value and the exports
parameter of the IIFE function.
There's a bit more that they pass in to the IIFE as well, but this shows the basic idea.