Private Variables in JavaScript

Ok, enough of this social/ranting stuff. Time to write something vaguely technical.

I have a love-hate relationship with JavaScript. I think anyone who works with it does. Sometimes it just doesn’t do what you expect, and it’s certainly different.

One trick, especially for people from real Object-Oriented languages like Java, Ruby, or let’s even say PHP 5, is the lack of access control. When everything is an object, the inability to hide certain values can become a problem.

Say, for example, you create an object that represents a product you sell, and you want to use one of your part numbers to identify the object. Let’s say the format for your part number is 1234-56. You might do something like…

1.
function Product (){
2.
    this.partNum;
3.
    this.setPartNum = function( num ){
4.
        if( partNumRegex.match(num)){
5.
            this.partNum = num;
6.
            returntrue;
7.
        }else{
8.
            returnfalse;
9.
        }
10.
    }
11.
}
You’re expecting the rest of your team to be respectful and use the `Product.setPartNum()` method, which should stop them from using an illegally formatted part number. (`partNumRegex` is left as an exercise to the reader.)

But what’s stopping them from doing this?

1.
var jacket = new Product;
2.
jacket.partNum = ‘1234’;
Now when they call your Ajax-driven `getProductData()` method, they’ll get an error. Had they used the `setPartNum()` method, they would’ve seen the error much earlier.

One trick to JavaScript is that variables are lexically scoped. Basically, functions use the value of a variable where they are defined, not where they’re executed, for example (or just read a better article):

1.
var a = 1;
2.
 
3.
function globalA(){
4.
    alert(a); //1
5.
}
6.
 
7.
function localA (){
8.
    var a = 2;
9.
    alert(a); //2
10.
}
So how does this help? Well, you can effectively hide values in a deeper scope. Instead of using the `this` keyword, just define new variables within your function:
1.
function Product (){
2.
    var partNum;
3.
    this.setPartNum = function(num){
4.
        // Fancy checking logic
5.
    }
6.
    this.getPartNum = function(){
7.
        return partNum;
8.
    }
9.
}
10.
 
11.
var tshirt = new Product;
12.
tshirt.partNum = 7;
13.
tshirt.getPartNum(); // null
This same thing can apply to private methods. Don’t want the new guy calling `superSecretInternalMethod()`? One common practice is to start private methods with an underscore, but a better way is to actually hide the method:
1.
function Product(){
2.
    var partNum; // private part number, use accessors
3.
    this.setPartNum = function(){
4.
        // as above
5.
    }
6.
    this.getPartNum = function(){
7.
        return partNum;
8.
    }
9.
 
10.
    function superSecretInternalMethod(){
11.
        // Whatever your coding-ninja heart desires
12.
        // I can access partNum
13.
    }
14.
}
15.
 
16.
var truck = new Product;
17.
truck.superSecretInternalMethod(); // JS Error: truck.superSecretInternalMethod is not a function.
We can even go a step farther and define private class methods and variables, but this post is already long enough, and it’s rare I have material for two in a row, so I’ll save that for next time.

If you haven’t read it, go get Pro JavaScript Design Patterns. You won’t regret it.