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).
use strict
thingie
2. The good ol' 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
&&
and ||
to create magic
4. Use 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:
- Google JavaScript Style Guide
- airbnb/javascript
- ... there are others too
- my style guide
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!
Thanks for the tips! Under section 5 I would additionally mention that you could create a string with Template literals: Template literals (Template strings)
I think there may be a typo in your ‘strict equal’ section. You have ‘==’ in the strict equal example instead of ‘===’.
for more tips like these -> jstips.co