4

I'm attempting to run this short program from Eloquent Javascript in the section on Modules.

var weekDay = function() {}();

(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")));

The proper output should be // -> Saturday.

It works perfectly in the browser. However, when I try to run it in the Node interpreter, I get this error:

TypeError: Cannot read property 'name' of undefined

I can only assume it has something to do with the way Node handles the exports keyword. Can somebody help me gain at least a rough understanding of this behavior?

8
  • 1
    It's probably this.weekDay. Try changing that to just weekDay. Commented Dec 27, 2015 at 20:26
  • 1
    Also the first line is useless. Just keep var weekDay; . Commented Dec 27, 2015 at 20:27
  • In Node modules, this is not global, but exports. Commented Dec 27, 2015 at 20:28
  • @AlexanderO'Mara, would you mind clarifying a bit on that point? Commented Dec 27, 2015 at 21:37
  • 1
    In Node modules, this is the exports object, which is pre-defined by Node. Commented Dec 27, 2015 at 21:49

3 Answers 3

3

The answer of Nir Levy is correct, but I posted this answer as well, because you were talking about Modules. This is how you make a module of your piece of code.

//create your module like this and put this module in a separate file (ex. weekDay.js)
var weekDay = (function() {
  var names = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];

  var name = function(number) {
    return names[number];
  };
  var number = function(name) {
    return names.indexOf(name);
  };

  return {
    number: number,
    name: name
  } 
})(); //it's a self executing function

//exporte module
module.exports = weekDay



//to get your module (in another file)
var weekDayModule = require('./weekDay'); //path to module

console.log(weekDayModule.name(weekDayModule.number('Saturday')));
Sign up to request clarification or add additional context in comments.

1 Comment

Don't hesitate to ask for more information if something is not clear ;)
2

in node.js this line:

var weekDay = function() {}();

just generates an undefined variable weekDay, since all it does is define a function with en empty body (the {} in your code) and run it right away. Since the body is empty (and most importantly, no return statement), it yields undefined

The way to do what you want is put the entire definition inside this function, and define what to expose, like this:

var weekDay = function() {
  var names = ["Sunday", "Monday", "Tuesday", "Wednesday",
    "Thursday", "Friday", "Saturday"];

  var name = function(number) {
    return names[number];
  };
  var number = function(name) {
    return names.indexOf(name);
  };

  return {
    number: number,
    name: name
  }

}();


console.log(weekDay.name(weekDay.number("Saturday")));

2 Comments

This solution was actually more or less the original working example used in the book. Haverbeke has this to say about the alternate version that I wrote out: "For bigger modules, gather all the exported values into an object at the end of the function becomes awkward since many of the exported functions are likely to be big and you'd prefer to write them somewhere else. A convenient alternative is to declare an object (conventionally named exports) and add properties to that whenever we are defining something that needs to be exported."
@ooronning: check my answer, this is the common way on how to export modules in a separate file
0

Change first line to var weekDay = {}; and when you invoke your iife then just put into it weekDay what you have created in the first line.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.