- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
Many object-oriented programming languages (Java and C++, for example) have the notion of private members: properties and methods that can only be seen, modified, and used from inside an object. The JavaScript language has no such feature. When you define a JavaScript class, all the methods and properties of that class are exposed. Your class has no clothes — everything about it is visible to any code that's using it.
But just because the JavaScript language doesn't have the notion of privacy doesn't mean you can't have it...
For example, if I were building a simple class to tally up the number of characters in a series of strings, I might do something like this:
function Test() {
this.count = 0;
}
Test.prototype.logger = function(x) {
gs.log(x);
}
Test.prototype.tally = function(x) {
this.logger('Tally ho!');
if (x)
this.count += x.toString().length;
}
Test.prototype.getCount = function() {
this.logger('Take that!');
return this.count;
}
var x = new Test();
JSUtil.logObject(x);
x.tally("Is my dog smarter than yon cabbage?");
x.tally("We'll never know, 'cause he just ate the cabbage.");
gs.log(x.getCount());
When I run this code, here's what I get:
Log Object
Object
count: number = 0
logger: function
tally: function
getCount: function
Tally ho!
Tally ho!
Take that!
84
The count property and the logger() method are there for any code to see — and to modify. Why does that matter? Well, a truly malicious programmer could tally up a bunch of strings, then change the count value to whatever he wanted it to be. That probably doesn't matter too much with a count like this, but if that value represented money you might care a little more. But it's really not intentionally malicious programmers that one wants to defend against — it's the accidental and generally innocent changes that you want your classes to be impervious to.
So in this case, I'd really like the count property and the logger() method to be private — entirely off-limits and invisible to any code using an instance of my Test class. Another feature of JavaScript (closures) lets me do it. Here's one way:
function Test() {
var count = 0;
function logger(x) {
gs.log(x);
}
this.tally = function(x) {
logger('Tally ho!');
if (x)
count += x.toString().length;
}
this.getCount = function() {
logger('Take that!');
return count;
}
}
var x = new Test();
JSUtil.logObject(x);
x.tally("Is my dog smarter than yon cabbage?");
x.tally("We'll never know, 'cause he just ate the cabbage.");
gs.log(x.getCount());
When I run this privatized code, I get:
Log Object
Object
tally: function
getCount: function
Tally ho!
Tally ho!
Take that!
84
That looks exactly like the preceding code, with one exception: the count property and the logger() method are completely missing from the object. They're invisible. They're private. Your code can't see them and can't change them.
How does this work?
There are two parts to the change I made. First, instead of relying on the prototype property to initialize the methods for my instance, I'm doing it directly in the constructor function (with the assignments to this.tally and this.getCount). Each of those properties has a function assigned to it.
Secondly, if you look at the bodies of those functions, you'll see that they refer to properties of the enclosing function (the constructor function itself). For example, each function refers to the count variable, which is defined in the enclosing constructor function. Because those two functions I'm assigning as properties are nested inside the constructor function, the constructor function and all it's properties are part of the scope chain for them. Here's where the little magic bit of closures comes in: when I assign that function to a property, the scope chain comes along with it — but it's hidden from view, and utterly inaccessible from outside the scope chain.
If you're not practiced in the art of closures, this can be a challenge to wrap your brain around. In many programming languages, there simply is no equivalent of this. The closures feature is quite a powerful one, useful for many things — and private properties in a class are a great example. It's another tool that's worth learning well...
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.