Star
1
Published Aug 15, 2016Last updated Nov 25, 2016

JavaScript Best Practices: Tips & Tricks to Level Up Your Code

JavaScript Best Practices: Tips & Tricks to Level Up Your Code

Learning new things everyday is part of what makes being a rational human being great. And as developers, it is part of our job to learn new things continuously, whether or not these things are from positive learning experiences.

In this tutorial, I will point out a few important JavaScript best practices so you don't have to learn it the hard way. Get ready to level to your code!

1. Avoid polluting the global scope

Declaring variables is a lot of fun. Sometimes, you may declare global variables even if you don't want to. In today's browsers, the global variables are stored in the window object. So, since there's a lot of stuff going on there, you may override default values.

Let's suppose you have an HTML file which contains a <script> tag containing (or which loads a JavaScript file containing):

var foo = 42;
console.log(foo);

This will obviously output 42 in the console. But since the code is not executed in a function, the context will be the global one. So, the variables are attached to the window object. This means that window.foo is 42 as well.

This is dangerous since you can override existing global variables:

function print () {
   // do something
}
print();

When executing window.print (or just print), it won't open the print popup since we have overriden the native print popup.

The solution is quite simple; we need a wrapping function that is called immediately, like below:

// Declare an anonymous function
(function () {
   var foo = 42;
   console.log(window.foo);
   // → undefined
   console.log(foo);
   // → 42
})();
//^ and call it immediately

Alternatively, you could choose to send the window and other globals (e.g. document) as arguments to that function (this will probably improve the performance):

(function (global, doc) {
  global.setTimeout(function () {
     doc.body.innerHTML = "Hello!";
  }, 1000);
})(window, document);

So, do use the wrapping function to prevent creating globals. Note that I'm not going to use the wrapping function in the code snippets below since we want to focus on the code itself.

💡 Tip: browserify is another way to prevent creating globals. It uses the require function the same way you do it in Node.js.

By the way, Node.js does wrap your files in functions automatically. They look like this:

(function (exports, require, module, __filename, __dirname) {
// ...

So if you thought the require function is a global one, well, it's not. It's nothing more than a function argument.

Did you know?

Since the window object contains the global variables and since it is a global itself, the window references itself inside:

window.window.window
// => Window {...}

That's because the window object is a circular object. Here's how to create such an object:

// Create an object
var foo = {};

// Point a key value to the object itself
foo.bar = foo;

// The `foo` object just became a circular one:
foo.bar.bar.bar.bar
// → foo

Or, to show your infinite love for JavaScript, you can make it fancier:

Yes, you can expand that object almost infinitely (probably until your browser crashes).

2. The good ol' use strict thingie

Strictly use use strict! This is nothing more than just adding string put in your code that adds more magic to your script.

For example:

// This is bad, since you do create a global without having anyone to tell you
(function () {
   a = 42;
   console.log(a);
   // → 42
})();
console.log(a);
// → 42

Using use strict, you can get quite a few more errors:

(function () {
   "use strict";
   a = 42;
   // Error: Uncaught ReferenceError: a is not defined
})();

You could be wondering why you can't put the "use strict" outside of the wrapping function. Well, you can, but it will be applied globally. That's still not bad; but it will affect it if you have code which comes from other libraries, or if you bundle everything in one file.

3. Strict equal

This is short. If you compare a with b using == (like in other programming languages), in JavaScript you may find this works in a weird way: if you have a string and a number, they will be equal (==):

"42" == 42
// → true

For obvious reasons (e.g. validations), it's better to use strict equal (===):

"42" === 42
// → false

4. Use && and || to create magic

Depending on what you need to do, you can make your code shorter using logic operators.

Defaults

"" || "foo"
// → "foo"

undefined || 42
// → 42

// Note that if you want to handle 0 there, you need
// to check if a number was provided:
var a = 0;
a || 42
// → 42

// This is a ternary operator—works like an inline if-else statement
var b = typeof a === "number" ? a : 42;
// → 0

Instead of checking if something is truly using an if expression, you can simply do:

expr && doSomething();

// Instead of:
if (expr) {
   doSomething();
}

That's even fancier if you need the result returned by doSomething():

function doSomething () {
   return { foo: "bar" };
}
var expr = true;
var res = expr && doSomething();
res && console.log(res);
// → { foo: "bar" }

You may not agree with me here, but this is more ideal. If you don't want to uglify your code this way, this is what these JavaScript minifiers will actually do.

If you ask me, though the code is shorter, it is still human-readable.

5. Convert values' types

There are several ways to convert these things depending on how you want to do it. The most common ways are:

// From anything to a number

var foo = "42";
var myNumber = +foo; // shortcut for Number(foo)
// → 42

// Tip: you can convert it directly into a negative number
var negativeFoo = -foo; // or -Number(foo)
// → -42

// From object to array
// Tip: `arguments` is an object and in general you want to use it as array
var args = { 0: "foo", 1: "bar", length: 2 };
Array.prototype.slice.call(args)
// → [ 'foo', 'bar' ]

// Anything to boolean
/// Non non p is a boolean p
var t = 1;
var f = 0;
!!t
// → true
!!f
// → false

/// And non-p is a boolean non-p
!t
// → false
!f
// → true

// Anything to string
var foo = 42;
"" + foo // shortcut for String(foo)
// → "42"

foo = { hello: "world" };
JSON.stringify(foo);
// → '{ "hello":"world" }'

JSON.stringify(foo, null, 4); // beautify the things
// →
// '{
//    "hello": "world"
// }'

// Note you cannot JSON.stringify circular structures
JSON.stringify(window);
// ⚠ TypeError: JSON.stringify cannot serialize cyclic structures.

6. Code Style/Style Guide

Follow the same code style across the files in the new projects. For existing ones, use the existing code style, unless you just decide to change it (tip: discuss that with your collaborators). Even if you create and document your code style, always follow it.

There are different existing code styles:

Bonus Tips:

Other important Javascript best practices you should remember are tools to help you format your code. Here are some of them:

  • js-beautify: Beautifies your code
  • UglifyJS(2): Uglifies/minimifies your code
  • jshint: Detects errors/potential problems in your JavaScript code
  • jscs: A configurable style guide checker

One last thing: debug your code, don't console.log.

Happy programming!

How to Really Ace JavaScript Interview Questions: The Comprehensive Guide
== vs === JavaScript: Double Equals and Coercion
Node.js Best Practices
Star
1