Search code examples
javascriptclosuresrevealing-module-pattern

cannot understand behavior of revealing module


I'm studying closures and revealing module pattern. It seemed to me I got it, but then during practice i found this strange "bug". Here's the code:

    const module=(function(){
    let counter=1;
  let incrCounter=function(){
  counter++;
  console.log(counter)
  }
  return { counter, incrCounter}
})();

module.incrCounter(); ///expected:2; output:2;
module.incrCounter(); ///expected:3; output:3
module.incrCounter(); ///expected:4 output:4

module.counter=1; 
module.incrCounter(); ///expected:2; output:5
module.counter; ///expected:5 (for some reason) ; output:1

I reread "You don't know JS" about closures. It has to work! I return an object with property "counter", so I should have the direct access to it. But it seems that i creating a new, local variable with the same name, and not updating the counter I want to. What am I doing wrong here?


Solution

  • When you do return {counter, incrCounter}, you are saying:

    • Copy the value of counter into the counter property of the return object
    • Then copy the value of incrCounter into the incrCounter property of the return object

    You are not saying to expose the internal counter variable, which means modifications to module.counter simply modify the copy, not the actual value. You can fix this by storing it in an object:

    const module = (function() {
        let ret = {counter: 1};
        let incrCounter = function() {
            ret.counter ++;
            console.log(ret.counter);
        };
        ret.incrCounter = incrCounter;
        return ret;
    })();
    

    Or, just using objects and this:

    const module = {
        counter: 1,
        incrCounter() {
            this.counter ++;
            console.log(this.counter);
        }
    };