Some common Javascript pitfalls

Javascript being both a dynamic and loosely typed language, gives you a lot of flexibility in our code implementation. With that said, if you are not careful, you might find yourself in one of the following pitfalls:

1) Undefined variables, unexpected values!

As usual if you declare variables using var, they will be in the scope in which they were declared. These variables are declared and can be assigned some value or null value. However unless you are in strict mode, undeclared variables will by default be in the global scope.

var x = 1;
function test(){
  var x = 2;
  y = 3;
  console.log('Calling x in test():' + x);
  console.log('Calling y in test():' + y);
}
console.log('x: ' + x);
test();
y = 4;
console.log('y: ' + y);

Output:
x: 1
Calling x in test():2
Calling y in test():3
y: 4

As you can see y has changed, although it was called outside the scope of the function test(). Now you know what to expect. As a rule of thumb you should always use typeof if you are unsure about the variable. For e.g:

function test(x, y){
  console.log('typeof x: ' + typeof(x) + ', typeof y: ' + typeof(y));
}
test(1, 'abc');
test(2);

Output:
typeof x: number, typeof y: string
typeof x: number, typeof y: undefined

2) Defining everything in the global scope

Its a good practice to define your variables and objects within a namespace. Let see with an example.

var person = {
  'name': 'John',
  'age': 25
}

Now you will that the person object is defined in the global scope as follows:

window.person

Object {name: “John”, age: 25}

What happens if you had included another javascript script which defines another person object globally after your script, lets say the object was declared like this:

var person = {
  'ssn': 1234,
  'name': 'Dave',
  'age': 30,
  'company': 'ABC'
}

Now call

window.person

You will find that your object has been overriden with the new object.
Object {ssn: 1234, name: “Dave”, age: 30, company: “ABC”}

Sometimes you may want to define your objects in the global namespace, lets say you created your own plugin. In this case you wrap everything within an object and only expose functions/variables that should be accessed globally.

3) Weird sorting order?

Try sorting the following array:

var num_arr = [3, 4, 1, 12, 7, 13, 24];
num_arr.sort();
console.log(num_arr);

You will get the follwing result:
[1, 12, 13, 24, 3, 4, 7];

The reason being that java script does lexical sorting. Hence you see that 12, 13 and 24 comes before 3.

You can change the sorting function using the following code;

sort(function(a, b){
  return a - b;
});

This will tell the sort method to compare which argument comes first. Putting the sort function above should give you the sorted array in ascending order as follows:
[1, 3, 4, 7, 12, 13, 24]

4) Callbacks and asynchronous Javascript

Lets say you want to make an asynchronous function call and on depending on completion you want to continue to the next statement as follows:

function asyncFunc(param){
  setTimeout(function(){
    console.log('Sleep for ' + param + ' seconds');
  }, param * 1000);
}
asyncFunc(3);
console.log('Call completed');

When you execute the function above you will see the statement following the function gets executed immediately:

Call completed
Sleep for 3 seconds

You can see that the asynchronous function is executed without blocking the other statements and therefore any statement following it will be executed immediately.

But in this case we want to execute the next statement only upon completion of the function call to asyncFunc.
So we use a callback function which is simply a function executed after the current function has completed.
We change the code above as follows:

function asyncFunc(param, callback){
  setTimeout(function(){
    console.log('Sleep for ' + param + ' seconds');
    callback();
  }, param * 1000);
}
function callback(){
  console.log('Call completed');
}
asyncFunc(3, callback);

which gives the following output:
Sleep for 3 seconds
Call completed

I hope this post helps you. Happy coding 🙂