0

I have the following function in my counter.js file:

//counter.js
var counter = 1;

function increment() {
  counter++;
}

function decrement() {
  counter--;
}

function getCounter() {
  return counter;
}

module.exports = {
  counter: counter,
  increment: increment,
  decrement: decrement,
  getCounter: getCounter
};

In my main.js, I have the following code:

//main.js
var counter = require('./counter');
counter.increment();
console.log(counter.counter); // 1
console.log(counter.getCounter()); // 2

I am unable to understand, why does the

counter.counter

gives 1 as output, whereas the

counter.getCounter()

gives 2 as the output.
What is the possible explanation for this behavior?

CoderX
  • 942
  • 1
  • 10
  • 30

2 Answers2

2

What is the possible explanation for this behavior?

JavaScript is pass/call/assign by value (and no, people who claim objects are passed by reference are wrong). That means when you did

module.exports = {
  counter: counter,
  ...
};

a copy of the current value of the counter variable (i.e. the value counter has at the moment that line is executed) is assigned to the counter property. Subsequently changing the value of the variable counter has no effect on the property counter.

Here is a simpler example of the situation:

var foo = 42;
var bar = foo;
foo = 21;
console.log(bar); // still 42, not 21

getCounter() on the other hand reads the value of the variable counter every time it is called, so it will always return the current value of the variable.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • Agreed naturally. Noting that a possible point of the OP's confusion may well be assuming the "module" is in the context of an "object" re: [Is JavaScript a pass-by-reference or pass-by-value language?](https://stackoverflow.com/a/3638034/2313887). Which of course a "module" is not. – Neil Lunn Oct 21 '17 at 03:18
0

Felix, of course, above has great explanation why this works the way it does. A nice solution to the problem (if you don't need to support old js) is to assign a getter on your export:

module.exports = {
    get counter() { return counter },
    increment: increment,
    decrement: decrement,
};

Now when you access counter.counter in your other script you'll really be calling a function that grabs the value of counter from your module.

Mark
  • 90,562
  • 7
  • 108
  • 148