Javascript's scoping got me
1 min read

Javascript's scoping got me

When programming, I often use a pattern like this one:

var myDefaultVariable;

for (var key in object) {
	
    myDefaultVariable = myDefaultVariable || getOtherVariable();
    
    // do stuff
}

The code above is not an exact form and it's something I use mostly when I have an original value that needs to be determined only for first object, keeping the value otherwise.

At the first iteration, it will be undefined, therefore executing the right side and setting a value. For the rest of the iteration, the value will remain the same and the computation will not be re-executed.

It saves me the hassle of extracting the first item, getting his value, and then re-iterating everything. For an array it's not that bad, you can simply do array[0] but for a javascript object it looks too ugly.

Anyway, I did something like this recently:

var myOrder = value;

myArray.sort(function (a, b) {
	
    var someLocalVar = someValue,
    	myOrder = (condition) ? myOrder : anotherOrder;
});

My (wrong) assumption was that if the condition is true, it will get the value from the parent scoping, otherwise it will change, this being true even if I was reusing the variable name and therefore redeclaring it.

When applying a sorting function to an array you have to keep in mind that a new scope will be created. And while I did have access to the variable myOrder inside the function, the moment I redeclared it, its value got overwritten to undefined.

Basically, this:
var myOrder = (condition) ? myOrder : anotherOrder;

became this:

var myOrder = (condition) ? undefined : anotherOrder;

Of course, this wasn't news to me, fortunately, but the fact that it was declared on a separate line, in a comma-separated declaration, threw me off a little. Had I had seen var in front of it, this wouldn't have happened.

This can be easily tested and verified with the following snippet:

var test = 'test';

var arr = [1, 2, 3];

arr.forEach(function () { 
    var test = test; 
    console.log(test); 
});

The console will log "undefined" three times, since var test declares a new variable inside forEach's scoping, overwriting the previous one.

Again, it's nothing uncommon, at least for someone who understands scoping and variables in javascript. But sometimes, if you're not paying attention, javascript gets you.

And this time, it got me!