Reputation: 27266
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
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