Here are two things that I don't very commonly see used in JavaScript applications, but may come in extremely useful.
"Private variables" variables for pseudoclasses
In a pseudoclassical instantiation pattern, it's quite common to see something like this:
var Foo = function(){
this._bar = 'bizzle';
this._baz = 'drizzle';
};
Foo.prototype.doThing = function(){
doStuffWith(this._bar);
};
Where, in this example, this._bar
and this._baz
have underscores to indicate that they are supposed to be "private" variables and shouldn't be touched. This is janky, since these variables aren't actually private. I would suggest that there is another way to do it, via getter and setter functions, and storing variables in closure.
var Foo = function(){
var stuff = {
bar: 'bizzle',
baz: 'drizzle'
};
this.set = function(attr, value){
stuff[attr] = value;
return value;
};
this.get = function(attr){
return stuff[attr];
};
};
Foo.prototype.doThing = function(){
doStuffWith(this.get('bar'));
};
Note, the getter and setter methods cannot be on the .prototype
of Foo
, because in order for these variables to remain private (in closure), the methods need a direct reference to stuff
.
Pros
-
You don't expose these variables as properties of the object. It leads to a cleaner object, and you don't have to use underscores to mark a false limiter on what properties should not be touched.
var thing = new Foo(); thing.set('bar', 'bizmack'); // => "bizmack" // the "bar" variable is not accessibile outside of the getter and setter. thing.bar; // => undefined // Setting thing.bar to something else does not affect what's returned by the getter thing.bar = 'boulder'; // => "boulder" thing.get('bar'); // => "bizmack"
-
You can easily handle logic on change, by adding that code into the getter and setter functions. If integrating with an event system, it may look something like this.
this.set = function(attr, value){ // stuff event.emit('change', attr, value); }
Cons
- Every new instance of
Foo
comes with its ownget
andset
functions. If I create 1000 objects withnew Foo()
, I also get 2000 extra functions. On a large scale, this can be expensive. - These variables aren't truly private, since the variables are still indirectly exposed via
get
andset
.
So is doing this any better than just defining variables as properties of each instance of the class? That's up to you to decide.
EDIT: It's been a year since I wrote this blog post, and I have never used this pattern. It just hasn't been very important that I make variables truly private.
Breaking out of each
loops
If you're using Array#forEach, or another utility function that repeatedly calls a callback, you can break out of it by throwing an error. This seems extremely hacky, but I think it's the only way to do it. In this example below, I simply create an object called breaker
, and throw it to "break" out of my loop. Since my forEach
is within a try..catch
block, I can catch all errors and check to see if the error is my breaker.
var breaker = {};
try {
[1,2,3,4,5].forEach(function(num){
if(num === 3){ // I picked an arbitrary point to break
throw breaker;
}
})
} catch(e) {
if(e !== breaker){
throw e;
}
}
In the catch block, it's important to throw your error again if the error is not your breaker, or handle them however you wish.
In most cases, it's completely unnecessary to write code this way. If something is going to be iterated over, it's better to just use a for
loop and use break
. However, sometimes it may be impossible to avoid using a each
-style loop, and in those cases, definitely look into doing this.