Multiple requires of same module seem to affect scope of each successive require

74 Views Asked by At

I created the following 3 files:

base.js

var base = {};

base.one = 1;
base.two = 2;
base.three = 3;

base.bar = function(){

  console.log( this.three );

};

a.js

var base = require('./base');
base.three = 6;
module.exports = base;

b.js

var base = require('./base');
module.exports = base;

test.js

var test_modules = ['a','b'];

test_modules.forEach( function( module_name ){
  require( './' + module_name ).bar();
});

And then run test.js like so:

node ./test.js

It outputs this:

6
6

Why is it that when I set the property 'three' of module 'base' in 'a.js', it then affects the object in 'b.js'?

2

There are 2 best solutions below

0
On BEST ANSWER

When you require() a module, it is evaluated once and cached so that subsequent require()s for the same module do not have to get loaded from disk and thus get the same exported object. So when you mutate exported properties, all references to that module will see the updated value.

0
On

You are introducing global state for base module.

The module a mutated base and then exported it as well, which means that any further references to base will have an updated value.

It is best demonstrated by the following script inside test.js

var testModules = ['b', 'a'];
testModules.forEach(function(module) {
  require('./' + module).bar();
});

Now when you run node test.js, you'll see

3
6

Why?

Because the order of inclusion of the modules changed.

How do I solve this?

Simple, get rid of global state. One option is to use prototypes like so

var Base = function() {
  this.one = 1;
  this.two = 2;
  this.three = 3;
};
Base.prototype.bar = function() {
  console.log(this.three);
};
module.exports = Base;

And then, inside a.js

var Base = require('./base');
var baseInstance = new Base();
baseInstance.three = 6;
module.exports = baseInstance;

And inside b.js

var Base = require('./base');
module.exports = new Base();

Now when you run your original test.js, the output should be

6
3