0

Note: regarding the comment about the similar question I would like to point out that I am not interested in the difference between module.exports and exports. Rather, my focus in this question is on the difference between exporting a function that - upon calling it - creates an object with the functions we wish to share versus directly assigning these functions as properties of the exports object.

I would like to understand the difference between the following two ways of exporting a module's functions (and hiding local state) in JavaScript:

way 1

var x = 0;

function get() {return x;}

function set(_x) {x = _x;}

exports.get = get;
exports.set = set;

way 2

module.exports = function () {
    var x = 0;

    function get() {return x;}

    function set(_x) {x = _x;}

    return {get:get, set:set};
};

(note that in way 2 I had to assign to module.exports, assigning to exports didn't work).

The way the code in way 1 is used is:

var gs = require('./get-set-a.js');

console.log(gs.get());
gs.set(100);
console.log(gs.get());

The way the code in way 2 is used is:

var gs = require('./get-set-b.js')();

console.log(gs.get());
gs.set(100);
console.log(gs.get());

When running both from the command line, under node.js I get identical results.

Is there any difference between way 1 and way 2 I should be aware of? Are they perhaps appropriate for different use cases? If not, which is more idiomatic?

Marcus Junius Brutus
  • 26,087
  • 41
  • 189
  • 331
  • @Andy been there and in similar places; not the same angle - which is why in my question I am only *mentioning* the fact that in the latter case I had to assign to `module.exports` as opposed to `exports` but am not dwelling any further or requiring any clarifications on that. – Marcus Junius Brutus Feb 13 '15 at 15:48
  • @close-voters: this is not a duplicate. Whilst there is confusion here between `module.exports` and `exports`, the actual question here about instances of modules, is not **mentioned** in the 'duplicate' let alone *covered* – Matt Feb 13 '15 at 23:00

1 Answers1

1

The second allows you to run multiple "instances" of your module, the first doesn't.


Using the first approach.

a.js

var gs = require('./get-set-a.js');

gs.set(100);
console.log(gs.get()); // 100;

require('./b');

b.js

var gs = require('./get-set-a.js');

console.log(gs.get()); // 100;

Using the second approach

a.js

var gs = require('./get-set-a.js')();

gs.set(100);
console.log(gs.get()); // 100;

require('./b');

b.js

var gs = require('./get-set-a.js')();

console.log(gs.get()); // 0;

Just to be perfectly clear, the multiple instance thing isn't because you're assigning to module.exports, rather than exports; it's because your initializer is returning a new closure each time it's called. You could achieve multiple instances with just exports as such;

get-set-b.js

exports.create = function () {
    var x = 0;

    function get() {return x;}

    function set(_x) {x = _x;}

    return {get:get, set:set};
};

c.js

var gs = require('./get-set-b.js').create();

console.log(gs.get()); // 0
gs.set(100);
console.log(gs.get()); / 100

d.js

var gs = require('./get-set-b.js').create();

console.log(gs.get()); // 0
gs.set(100);
console.log(gs.get()); // 100
Matt
  • 74,352
  • 26
  • 153
  • 180