O'Reilly

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!

Track.js Error Reporting

Upcoming Events

Recent Features

  • Create a Sheen Logo Effect with CSS

    I was inspired when I first saw Addy Osmani's original ShineTime blog post.  The hover sheen effect is simple but awesome.  When I started my blog redesign, I really wanted to use a sheen effect with my logo.  Using two HTML elements and...

  • I’m an Impostor

    This is the hardest thing I've ever had to write, much less admit to myself.  I've written resignation letters from jobs I've loved, I've ended relationships, I've failed at a host of tasks, and let myself down in my life.  All of those feelings were very...

Incredible Demos

  • LightFace:  Facebook Lightbox for MooTools

    One of the web components I've always loved has been Facebook's modal dialog.  This "lightbox" isn't like others:  no dark overlay, no obnoxious animating to size, and it doesn't try to do "too much."  With Facebook's dialog in mind, I've created LightFace:  a Facebook lightbox...

  • Create Twitter-Style Buttons with the Dojo Toolkit

    I love that JavaScript toolkits make enhancing web pages incredibly easy. Today I'll cover an effect that I've already coded with MooTools: creating a Twitter-style animated "Sign In" button. Check out this five minute tutorial so you can take your static...

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!

Recently on David Walsh Blog

  • Get Node.js Command Line Arguments with yargs

    Using command line arguments within Node.js apps is par for the course, especially when you're like me and you use JavaScript to code tasks (instead of bash scripts).  Node.js provides process.argv but that doesn't provide a key: value object like you'd expect: Bleh.  If you want to work with a...

  • OâReilly Velocity Conference â New York

    My favorite front-end conference has always been O'Reilly's Velocity Conference because the conference series has focused on one of the most undervalued parts of client side coding:  speed.  So often we're so excited that our JavaScript works that we forget that speed, efficiency, and performance are just as important. The next Velocity...

  • Free Download: Font Bundle Featuring 17 Incredible Typefaces

    The only thing we love more than a good font, is a good free font. So we’ve combed the Web for some of our favorite free fonts, and gathered them here in a single download. You’ll find a variety of useful typefaces, from highly geometric designs...

  • OâReilly Velocity Conference â Amsterdam

    My favorite front-end conference has always been O'Reilly's Velocity Conference because the conference series has focused on one of the most undervalued parts of client side coding:  speed.  So often we're so excited that our JavaScript works that we forget that speed, efficiency, and performance are just as important. The next Velocity...

  • CanIUse Command Line

    Every front-end developer should be well acquainted with CanIUse, the website that lets you view browser support for browser features.  When people criticize my blog posts for not detailing browser support for features within the post, I tell them to check CanIUse:  always up to date, unlike...