Marcus Junius Brutus
Marcus Junius Brutus

Reputation: 27266

difference between module export idioms

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?

Upvotes: 0

Views: 134

Answers (1)

Matt
Matt

Reputation: 75307

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

Upvotes: 1

Related Questions