Hiding Your Privates with JavaScript

By  on  
JavaScript Privates

Believe it or not, there are a lot of people who strongly dislike JavaScript. For one reason or another, they simply can't stand the perceived lack of security and structure within the language. One of those perceived weaknesses is lack of the private designations for variables within structures. They have a point; if you stick a property on an object, or create d global variables, it's fair game for anyone. There is, however, a few very simple patterns you can use within JavaScript to keep access to a given object or variable private!

With "Classes"

You probably know that true classes don't exist in JavaScript, but using Function and prototypes we can simulate them pretty damn well. Using this pattern, you can also simulate private variables:

function MyClass(parameter) {
	
	// Create the private var
	var privateVar = 8,
		self = this;
	self.parameter = parameter
	
	// Function that handles the private
	function handlePrivate() {
		return privateVar ? privateVar-- :  false;
	}
	
	// Public method that calls the handler
	// Returns parameter until it's been accessed 8 times
	this.getPrivate() {
		return handlePrivate() ? self.parameter : null;
	}

}

Privates are made within the constructor and only the constructor. Adding privileged methods within the constructor give access to privates. In the sample above, the value is accessible only by the privileged method.

With Closures

The pattern centers around a closure with a scoped variable, returning an object or function with access to the variable. Here's a simple example:

var accessor = (function() {
	// Create the private var
	var privateVar = "You Can't See Me, ";
	
	// Some other functionality here that periodically changes privateVar, because it has access to it
	// [ more code here ]
	
	// Return the accessor
	return function(name) {
		return privateVar + name;
	};
})();

// Use!
// currentValue = accessor("David");  "You Can't See Me, David"

The privateVar variable is not available out side the closure so there's no way to access it directly. We do, however, have a define function with access to the variable and return that from the closure. Thus, the variable stays private, you can access its value, but no direct access is allowed. You could also return an object with methods for modifying the protected variable:

var accessor = (function() {
	
	// The "private"
	var val = 9;
	
	// An object for getting and setting
	return {
		get: function() {
			return val * 3;
		},
		set: function(s) {
			val = s;
		}
	};
})();

Of course, with the pattern above, a user could reassign the get method with something like:

accessor = function(n) { return "My custom string, " + n; }

..so be aware of that. Usually any functionality that handles private information stays within the closure, preventing issues with users overriding methods. Something like this:

var accessor = (function() {
	
	var permissions = {};
	
	function handleResult(perm) {
		// Do something with the result
	}
	
	return function(permissionToCheck, callback) {
		if(permissions[permissionToCheck]) != undefined) {
			callback(permissions[permissionToCheck]);
		}
		else {
			$.post({
				url: "/permissions"
				data: {
					perm: permissionToCheck
				}
			}).success(function(res) {
				callback(handleResult(res));
			});
		}
	};
	
})();

There's a certain beauty in the simplicity of JavaScript; don't write it off because it doesn't provide the same explicit structures as other languages!

Recent Features

  • By
    Create Namespaced Classes with MooTools

    MooTools has always gotten a bit of grief for not inherently using and standardizing namespaced-based JavaScript classes like the Dojo Toolkit does.  Many developers create their classes as globals which is generally frowned up.  I mostly disagree with that stance, but each to their own.  In any event...

  • By
    Creating Scrolling Parallax Effects with CSS

    Introduction For quite a long time now websites with the so called "parallax" effect have been really popular. In case you have not heard of this effect, it basically includes different layers of images that are moving in different directions or with different speed. This leads to a...

Incredible Demos

  • By
    Detect Vendor Prefix with JavaScript

    Regardless of our position on vendor prefixes, we have to live with them and occasionally use them to make things work.  These prefixes can be used in two formats:  the CSS format (-moz-, as in -moz-element) and the JS format (navigator.mozApps).  The awesome X-Tag project has...

  • By
    CSS Columns

    One major gripe that we've always had about CSS is that creating layouts seems to be more difficult than it should be. We have, of course, adapted and mastered the techniques for creating layouts, but there's no shaking the feeling that there should be a...

Discussion

  1. Salman Abbas

    Usually I hide my privates like this but when using Backbonejs I just use underscore prefixed method names so that child classes can inherit those methods.

  2. Could you include an example of usage of the first class? Thanks a lot :)

  3. I think there’s a typo in the last example:

    .success(function(res) {
            callback(handleResult());
          });
        }
    

    Shouldn’t res be passed to handleResult?

    .success(function(res) {
            callback(handleResult(res));
          });
        }
    

    Also, echoing @REINE, it would be great if you could provide usage examples throughout as you did first closure.

  4. When programming with prototypes (“classes”) it can be tough to enforce good scope and write good code. That is, in your first example, you define a function within a function. While there’s nothing illegal about this, it’s not especially efficient, since the function is actually going to be created as a totally new function (not just a separate stack frame) every time you create an instance of that prototype.

    This would definitely scale badly if this class had a lot of private “methods” and you created a lot of instances of it. There are two ways to avoid this, and neither are ideal.

    First, you can create the prototype itself inside a closure, and refer to functions that are defined in the closure, but outside the prototype. This is bad because the functions have no scope. You would have to invoke them with the context every time, e.g.

    somePrivateFunc.apply(this,args);
    

    This is ugly and a pain. The other way is to include them in the prototype, and use some convention to identify them as private (like an underscore prefixing the name). I do this a lot. While you do open yourself up to abuse since there’s nothing stopping any user of the “class” to access those methods, let’s remember this is javascript: anyone can always monkey patch your stuff and do whatever they want. It’s impossible to stop abuse if that is the goal.

    I think you have to decide what lengths you’ll go to to enforce good code writing. I usually fall in “I want stuff on the prototype” for complex classes because it’s too risky and difficult to manage other ways.

  5. gby

    That’s exactly why many programmers with experience in better languages hate JS. Things that should be obvious (build into the very syntax of the language ) need patterns and tricks. That sucks, badly. In any big enough project you have to do so many things that thinking about how to make variable private is ridiculous waste of time and money. Don’t get me wrong, I know JS and I use it a lot. I just wish there would be some alternative…

  6. Aale

    Yes JavaScript sucks but not because it exposes its privates.
    Why should it be a big problem to expose them?
    You/team write the code with full knowledge of what is what.
    “ it’s fair game for anyone “
    SO WHAT…
    Jamie hit the nail on the head when he mentioned about what people can do with your script.
    When it goes public you just have to worry that it works correctly. NOT to impress your peers…
    YOU just make sure you the developer understand what you are doing…
    With all that said…
    Yes we need good structure in a language and peer reviews are just one way to achieve that.

  7. Jos

    @Aale: maybe you should rephrase your contribution to something like “Sorry, but I am a rookie and at this moment I do not understand why hiding of variables is necessary, maybe anyone can give me a clue and enlighten me?”

    • Tim

      I wish you had given a counterpoint. If we were as convinced of your prowess as you seem to be, what practical advice or insight would you have to offer? If.

  8. Kamil Szot

    Please don’t hide your private methods. Namespace them by all means but leave a way to access them from outside.

    There’s nothing I hate more than not being able to compose parts of the library I’m using in ways API designer haven’t anticipated.

    At the moment I’ll need to compile my own version of d3js just because their creators hid d3_time_scale and related stuff.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!