Thursday, September 18, 2008

Truly private instance variables in JavaScript

Standard javascript objects do not support truly private instance properties (at least in a cross platform fashion). This means that even if you create get- and set-methods for your properties, an evil abuser of your interface can always get around this by simply peaking inside the object.

Leaving the arguments aside whether this is actually a problem or not, one can achieve the affect of private instance properties that only grant access through accessor methods by using closures which refer to a storage variable. A downside of this technique is the increased memory usage and increased object construction time, because these closures will have to be created upon every object construction so that the new object refer to their own private storage variable.

Here is some code that is demonstrating this technique:
MyClass = function () {
makePrivate(this, "test")
};

function makePrivate(object, name) {
var storage;

var field = name;

object[field] = function (newVal) {
if(arguments.length > 0) {
storage = newVal
}
return storage
}
}


var o1 = new MyClass();
var o2 = new MyClass();

o1.test(1)
o2.test(2)

alert(""+ o1.test() + o2.test())

o1.test(3);

alert(""+o1.test() + o2.test())


Another downside to this technique is that your instance vars are so private, even firebug cannot see them, so debugging will be much harder.

I'm currently pondering whether this technique would be a nice addition to Joose (hidden behind the regular class construction syntax). Putting this inside an attribute meta class would at least allow to enable a kind of debug mode that would make the vars visible during development.

While privacy might not be so relevant when you build all code for yourself, it might still be useful when you build a public JS API like Google Maps. True information hiding makes the interface much more explicit and enables you to change the internal representation of your objects later on without having to take care of people who relied it.
Post a Comment