5 Tips to Become a Better JavaScript Developer

js_logoJavaScript is still a mystery to a lot of people. With it’s growing popularity with things like Node.js, Angular.js, and jQuery, people are wanting to know more and more about the language. With more beginners jumping in, there’s room to make mistakes that JavaScript will more than willing let you do. This list is composed of mistakes that I see people make that don’t quite grasp some of the more complicated aspects of JavaScript. Some of these you can implement right now, others take some additional learning. Let’s begin!

Tip #1: Understand ‘this’

I don’t mean ‘this’, as in JavaScript, but the keyword this. In other languages like C++, C#, and Java, this refers to the current instance of whatever class in which it is being used. In those other languages, this is a pretty static and easy to decipher concept. In JavaScript, it isn’t that simple. Not only can the value of this be different depending on the situation, but you as the developer can have it be whatever you want it to be. In basic JavaScript execution, this will refer to the window object, or the Global scope. That’s because most of basic JavaScript code is executing within the Global scope:

This says that this is ‘window’ both inside foo and in the Global context. Now that you know what the default for this is, there are instances where it is not ‘window’. The first being when creating JavaScript ‘classes’. I put classes in quotes because JavaScript doesn’t have what most people know as classes. JavaScript is based on prototypes so modifying an object’s prototype is how you would construct classes. When extending an object’s prototype, this will reference the object being modified. This is more akin to how C# or Java handles this. Let’s take a look at that:

You might be asking, why isn’t this refer to the window object inside the Person function? It’s because we are creating a new instance of that object. When using the new keyword, this then refers to the newly created object. That Person function then acts as a sort of constructor for our new class. Just like I mentioned earlier, when modifying the object’s prototype also gives you access to that object. The next weirdness when it comes to this, is .call(), .apply(), and .bind(). Call and apply are pretty similar. Instead of calling a function normally, you can call it as well as modify what this will be inside that function. Using the first example from above, this will do a better job of explaining it than I could:

As we called foo we changed the value of this as shown by the console output. call and apply also differ on how you would pass in the parameters required by the function. This is explained well herebind is a little bit different. It will return a new function that anytime that new function is called, has the value of this that you specified in the bind. For example:

As you can see, this isn’t straightforward. You really have to be careful when using it if you don’t understand the context in which it’s being used. With that in mind, it can be a powerful tool knowing that you have that flexibility.

Tip #2: Recognize Scope and Variable Hoisting

One of the biggest differences JavaScript has from other well-known languages is the concept of scope. Scope describes the lifetime of a variable, functions, or named properties depending on where and how that thing is declared. Some of the familiar types are Block scope, Global scope, and Function scope.  JavaScript has what’s called Lexical scoping at the function level. So what does that mean? Let’s take the following code:

When foo() is called, the output will be ‘5’ since bar has access to x even though it was declared outside its own scope. This is called Lexical Scope, or Static Scope.

Next on the list is hoisting. Variable hoisting can be quite confusing and it is a concept pretty unique to JavaScript. Take the following code:

What do you think the console output will look like? Using scope, it looks like it will be ‘a’, ‘a’, ‘b’. What it actually outputs is ‘a’, undefined, ‘b’. That’s interesting isn’t it? What’s actually going on is when ‘x’ is declared again inside of bar, the declaration is moved to the top of the scope, or the function when the code is parsed. bar then looks like this:

Now it starts to make sense why the output looks like it does. The value of x is actually undefined when getting to the first console.log. Scope and hoisting are two important concepts that can be difficult to understand and debug, but grasping them will hands down make you better JavaScript developer.

Tip #3: Avoid Global Scope

Now that you have a better grasp on how scope and this works in JavaScript, if at all possible, avoid creating variables and functions on the global scope. This is one of the simplest, but often overlooked, debugging and performance enhancements you could do to any app. In other words, don’t do this:

Both x and foo now exist on the global scope. Not only is this a slow look up since the interpreter has to search a mess of objects to find it, but if there’s anything that exists already called x or foo, you’ve now just overwritten them with new values. That could break other things in your app and trying to track down that bug is not easy. The best trick to avoid this, is to wrap every file in an IIFE (pronounced ify):

This creates a function scope in the file so that anything declared inside of it, the look up chain only needs to look within that file. If you are really a stickler for performance, you can take this one step further but passing in global variables as parameters to your IIFE:

Any code that looks for those globals can skip looking them up in the Global scope.

Tip #4: Ditch the jQuery Crutch

Although I mentioned jQuery, this can be applied to any library. A majority of what jQuery does can be easily achieved using plain JavaScript. jQuery does provide fixes for cross browser issues, plus a great fluent api, but this only applies to the more complicated functions. There’s quite a few developers that only use jQuery for the selector engine to target elements in the DOM. There are two functions that are provided to you through the document object called, querySelector and querySelectorAll. They provide a simplified selector engine that use similar syntax to jQuery. querySelector will only select a single node:

While querySelectorAll will return a NodeList, which is different from an array. You can loop over it with a for loop:

Obviously this won’t cover everything, but if you just need a basic selector engine, querySelectorAll will work just fine for some situations.

What I’m saying is don’t rely heavily on jQuery, or any other library, without having some sort of understanding of how that library is accomplishing it’s tasks. If you can accomplish the same thing by using vanilla JavaScript, most of the time, it’s more efficient to do so. Cross browser oddities can get in the way of this when talking about more advanced tasks, but use your judgement.

Tip #5: Always Use ‘use strict’

JavaScript doesn’t have a compiler meaning that it will let you shoot yourself in the foot and then give you no help on how to fix it. The only real help you can give yourself without using tools like JSHint, is to turn on strict mode in your JavaScript files. You turn that on by adding this at the top of your files:

This turns it on for the whole scope of the file. If you are using the IIFE that I mentioned in tip #3, it would look like this:

Well what does strict mode give you? It won’t solve all your issues, but it will cause some browsers to throw additional errors in the console. For instance, in strict mode, you must declare all variables with the var keyword:

There’s a long list of mistakes strict mode will turn into errors. You can read the full list on the Mozilla Developer Network. If you don’t have this in your JavaScript, add it now as it’s the closest thing to a built in compiler you get.

Fin

If you’ve made it this far, congratulations! Hopefully you are now a betterJavaScript Please Work
JavaScript developer. I went through some of the concepts pretty quickly as I mostly wanted to pique your curiousity. I encourage you that if JavaScript development is in your future, I recommend reading up more on some of them, especially scope, inheritance, and the this keyword. Although they seem mysterious, they can become vital tools to building great JavaScript apps and to become a better JavaScript developer.


Update 8/22/2014: Fixed second code sample under tip #2.
Update 8/23/2014: Revised some of the concepts.