Thursday, May 21, 2015

Private Variables in Javascript without Constructors or Funky Underscores

TL;DR

var x = function(){
  var id = 0;
  x = function() { return id++;};
  return x();
};

Explanation

Normally people use either a constructor function to capture hidden variables in the parent scope,

var X = function(){
  var id = 0;
  return function(){ return id ++;};
};

var x = X();

Or they'll use the weak _ prefix to signal to other developers that a given variable shouldn't be touched.

var x = function(){
  return x._id++;
};

x._id = 0;

The former is more verbose than I care to have, especially when I only ever need a singleton or something akin to a generator. The latter makes that id variable public, which makes me uneasy as it can be accessed by other bits of code in ways I didn't designate. For most things, I like this way better:

var x = function(){
  var id = 0;
  x = function() { return id++;};
  return x();
};

By reassigning the function to a function within itself, the scope of the original is captured, and in that closure we can hide all our precious private state. That reassignment only happens once though, so subsequent calls to the function don't continue to spin off new scopes (but they do still have access to the private variables).

Footnote

This is a quick way to cheat at making generators now in vanilla, non-compiled Javascript without waiting for ES6 or having to use a tool like Babel. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators#Generators See this MDN article for comparison.

No comments: