JavaScript is an easy to learn programming language. It’s easy to write programs that run and does something. However, it’s hard to account for all the uses cases and write robust JavaScript code.
In this article, we’ll look at some good features of JavaScript that we should use to write robust JavaScript code.
Use === Instead of ==
In JavaScript, there’s the ===
and ==
operators for determining the equality of 2 entities.
==
coerces the type by following a long list of rules before doing the comparison between its 2 operands.
On the other hand, ===
doesn’t do any data type coercion before comparing its operands.
This makes ===
better since JavaScript’s data type coercion creates weird results that we don’t expect.
Using the ==
operator leads to expressions like 0 == false
returning true
.
We don’t want to make things a lot harder by saving one character on our code, so we should always use ===
to do equality comparisons.
Likewise, to check for inequality, we should use the !==
operator, which also doesn’t do any data type coercion before comparing its operands for inequality.
Never Use Eval
eval
lets us run code that’s embedded in a string. This means that theoretically, any user can run anything as long as they can set the value of the string that we pass into eval
.
The code in eval
runs in global scope so it can have a big impact if we let anything run with eval
.
Therefore, we should avoid this at all costs. Also, it decreases our app’s performance since running code from a string means that the JavaScript interpreter can’t do any performance optimizations beforehand.
Never Use the Function Constructor
The Function
constructor is like eval
. It lets us define a function by passing in the code that we want to run inside the function.
For instance, we can pass in the parameter names and the function body as strings by writing the following:
const add = new Function('x', 'y', 'return x + y');
In the code above, we invoked the Function
constructor with the 'x'
and 'y'
strings, which are the parameter names. Then we have 'return x + y'
as the 3rd argument to return the sum of x
and y
.
We can then run our function as follows:
const sum = add(1, 2);
Like eval
, we dynamically pass in strings to write our code. It also runs everything in the global scope and prevents optimizations just like eval
does.
It also has the same security issues as eval
since we still pass in strings to define our functions.
Therefore, we also shouldn’t use this to define our functions.
Don’t Pass in Strings as Code in setTimeout and setInterval
The setTimeout
and setInterval
functions allow us to run code after a delay and run code in a specified interval respectively.
One feature we shouldn’t use in either of them is passing strings into them to run code.
For instance, we shouldn’t write something like the following:
setTimeout('console.log("foo")', 100)
This will run console.log("foo")
after 100 milliseconds, but we shouldn’t do this since again, we’re running code from a string which presents the same security and performance issues as the other occasions where we run code from a string.
Therefore, we should always run code that’s defined with code instead of a string, like the following:
setTimeout(() => console.log("foo"), 100)
The code above runs console.log
like it does with the string, but the JavaScript interpreter can optimize the code and there’re no security issues since there’s no risk that attackers can inject code into our app as a string.
Always Add Semicolons and Parentheses
Semicolons should always be added to make our code as clear as possible. JavaScript can insert semicolons automatically when we don’t do it ourselves. Parentheses can also be optional with one-line if
blocks.
It’ll insert it when it thinks it should be a new line, like in any logical break that it finds.
However, it often leads to confusion. If we write something like the following:
if (foo)
x = false
bar();
Then we may think that both lines are run if foo
is true
. But this isn’t the case.
The JavaScript interpreter will think that only x = false
is part of the if
block and bar()
is separate.
Therefore, if we want to eliminate confusing code like this, we should write:
if (foo) {
x = false;
bar();
}
to delimit our lines and blocks with semicolons and parentheses.
This way, we know that they both will run if foo
is true
.
Conclusion
===
and !==
are always better than ==
and !=
for equality and inequality comparisons respectively.
Also, we should never run code from a string with eval
, the Function
constructor, setTimeout
, setInterval
or any other place that allows us to do that.
Finally, we should add semicolons and parentheses to delimit our code blocks.