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.