Bullet-proofing Setters and Getters
JavaScript has two very handy methods that you can use on an object:
__defineSetter__(), and __defineGetter__(). They allow you to write
accessor functions for your objects. Here, I’ll show you how to write them so
they are as tamper-free as possible.
I needed a bullet-proof pattern for accessors for my Daimyo library that I use to hook Herd Hound to Samurai payment gateway.
Now, before I begin, it should be noted that method that I’ll be showing you
here actually covers only simple types (String, Number, RegExp, and
Date). Composite types like Object or Array require a different
approach, which I will only briefly mention, with a link to useful code that
can get you there.
So, let’s get started. First the normal way to do accessors:
function Constructor() {
var self = this;
self.__defineSetter__('prop', function(val) {
self._prop = val;
});
self.__defineGetter__('prop', function() {
return self._prop;
});
}
These are simply setting and returning a different property that will hold the real value. Obviously, you’d do more complex stuff to the incoming or outgoing value, which is the point of accessors.
Let me demonstrate one teeny-weeny problem with this:
var myObj = new Constructor();
myObj.prop = 'foo';
console.log(myObj.prop); // => 'foo'
console.log(myObj._prop); // => 'foo'
myObj.prop = 'bar';
myObj._prop = 'foo';
console.log(myObj.prop); // => 'foo'
So obviously, our _prop property is exposed, and anyone can play with it.
It’s all cool as long as you are dealing with a well-behaved developer who will
respect the API and never touch stuff that starts with an underscore (except,
obviously, the __defineGetter__(), and __defineSetter__()). But what
if, in a very unlikely but still remotely possible scenario, malicious attacker
(or just some kid armed with too much free time and super-human curiosity)
manages to compromise the app that uses this API? In that case, it is quite
possible that the app is tricked into setting the _prop instead of
prop, and circumventing any carefully written validation logic in our
setter function.
Naturally, our instinct tells us (or is it paranoia?) that we should tuck away
the _prop property somewhere where nobody can play with it (not even the
kids). A good solution for this is to use closures.
function Constructor() {
var self = this;
(function(self) {
var propVal;
self.__defineSetter__('prop', function(val) {
propVal = val;
});
self.__defineGetter__('prop', function() {
return propVal;
});
}(self));
}
Before you go ‘WTF’ on me, I’ll explain what happened. So, first thing first:
(function(args) {
}(args));
This pattern is called immediate function invocation. What we do is, we define a normal function, and then call it immediately. Note that the function we’ve defined has a closing curly bracket, followed immediately by a set of round brackets with arguments in them (last line of the last snippet). This tells it to immediately call itself with the specified arguments, which are passed to it (surprised?). The whole thing is then wrapped in round brackets to signify that it’s an expression that has to be evaluated on the spot.
One cool thing about this is that this function is sealed from the rest of the
world. What’s uncool about it is that it’s sealed from the rest of the world.
You can take that any way you want. What it means is that it cannot access
variables defined outside (like self in our example), so you have to pass
them to it.
Closure pattern is this one:
(function(args) {
var someVar;
return function() {
// We can access someVar from here, but nobody else can!
};
}(args));
The outer function (the immediate function expression) closes over the one defined inside it. Note that, as long as we have one function closing over the other, we don’t actually have to use the immediate function expression, but in this case it came quite handy, because we needed a one-off function that won’t be used again.
Now, the cool thing about closures is that they are so awesome. Seriously. Anything defined in the outer function is accessible to the inner function even after the outer function is done. The inner function can then be called at some later stage in execution, while still maintaining the knowledge of the stuff that was defined outside it.
So, in our accessor example, we define the variable that will store the property’s value in the closing function, and the inner functions (accessor functions) will use this variable to set and return the value of the property. The variable is visible only to accessors, and nobody can tamper with them (not even the kids).
There’s one exception to the above tamper-free claim. If the values are objects, then they can still be tampered with, because, as we’ve seen before, objects are passed by reference, not by value. This allows anyone to manipulate the properties of the value stored in the closure after it’s returned by the getter function. To avoid this, you need to return a cloned object. Code to do that is available in a Gist by Brian White, so I won’t go into details of how it works. As an aside, if it’s a simple object whose properties only contain non-object values, you can do this in your getter:
var clone = {};
Object.keys(valueInTheClosure).forEach(function(key) {
clone[key] = valueInTheClosure[key];
});
return clone;
That’s called shallow copying.




