Fernando Ferreira
Fernando Ferreira

Reputation: 51

What's the reason of the following JavaScript syntax when using closures?

Studying about closures, I looked at the Developer's Mozilla article about it and saw the code below:

var counter = (function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }

  return {
    increment: function() {
      changeBy(1);
    },

    decrement: function() {
      changeBy(-1);
    },

    value: function() {
      return privateCounter;
    }
  };
})();

console.log(counter.value());  // 0.

counter.increment();
counter.increment();
console.log(counter.value());  // 2.

counter.decrement();
console.log(counter.value());  // 1.

I'm confused about how the function is attributed to the variable counter, because the function is initially envolved by those parentheses, and after all, there are also two unreaseble parentheses together... I just wondered, what's the reason of that syntax? I certainly would do:

var counter = function() {
  var privateCounter = 0;
  function changeBy(val) {
    privateCounter += val;
  }

  return {
    increment: function() {
      changeBy(1);
    },

    decrement: function() {
      changeBy(-1);
    },

    value: function() {
      return privateCounter;
    }
  };
};

But then I got the error

Uncaught TypeError: counter.value is not a function

When I do console.log(counter.value());

Can someone please explain it to me?

Upvotes: 1

Views: 45

Answers (1)

Nicholas Tower
Nicholas Tower

Reputation: 84922

What you're looking at is an Immediately Invoked Function Expression or IIFE. This code is creating a function, then immediately calling that function, then assigning the return value of the function to counter. So counter isn't a function, it's an object with three properties: increment, decrement, and value.

The reason that they used an IIFE was to make what's essentially a private variable. privateCounter is only in scope to other code inside that function, which means only increment, decrement, and value can access it.

If they didn't care about making the variable private, the equivalent code would be:

var publicCounter = 0;
function changeBy(val) {
  publicCounter += val;
}

var counter = {
  increment: function() {
    changeBy(1);
  },
  decrement: function() {
    changeBy(-1);
  },
  value: function() {
    return publicCounter;
  }
}

Upvotes: 2

Related Questions