Treehouse

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!

ydkjs-3.png

Recent Features

  • 6 Things You Didn’t Know About Firefox OS

    Firefox OS is all over the tech news and for good reason:  Mozilla's finally given web developers the platform that they need to create apps the way they've been creating them for years -- with CSS, HTML, and JavaScript.  Firefox OS has been rapidly improving,...

  • 9 Mind-Blowing WebGL Demos

    As much as developers now loathe Flash, we're still playing a bit of catch up to natively duplicate the animation capabilities that Adobe's old technology provided us.  Of course we have canvas, an awesome technology, one which I highlighted 9 mind-blowing demos.  Another technology available...

Incredible Demos

  • Create Keyboard Shortcuts with Mousetrap

    Some of the finest parts of web apps are hidden in the little things.  These "small details" can often add up to big, big gains.  One of those small gains can be found in keyboard shortcuts.  Awesome web apps like Gmail and GitHub use loads of...

  • AJAX For Evil:  Spyjax with jQuery

    Last year I wrote a popular post titled AJAX For Evil: Spyjax when I described a technique called "Spyjax": Spyjax, as I know it, is taking information from the user’s computer for your own use — specifically their browsing habits. By using CSS and JavaScript, I...

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 codewriting. 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?”

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