JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.
In this article, we’ll look at loops that we shouldn’t have, and useless labels, catch
clauses, and call
and apply
calls that are useless.
No Unmodified Loop Conditions
If we have a while
or do...while
loop with an unmodified condition, the loop will run forever as the loop condition hasn’t been updated with a new value.
This is usually not what we want as it’ll crash our program most of the time because of the infinite loop.
However, infinite loops are sometimes appropriate for functions like generator functions that return the latest value when the generator is created from the function and invoked.
Therefore, in a regular while
loop, we probably shouldn’t write an infinite loop:
while (condition) {
doSomething();
}
However, it’s appropriate for generator functions that return an infinite number of entries:
function* num() {
let i = 1;
while (true) {
yield i;
i++;
}
}
const iterator = num();
const val = iterator.next().value;
const val2 = iterator.next().value;
In the code above, we have the num
generator function while returns a new integer after we created an iterator
from it by calling it, and then calling next
on it one or more times to get the value one at a time.
For regular while
or do...while
loops, we should almost always have a condition that changes.
For instance, we can write the following:
let x = 1;
while (x <= 5) {
console.log(x);
x++;
}
The code above has a condition that ends the loop as we increase x
by 1 until x
is 5.
No Unused Expressions
Some JavaScript expressions in our code are useless as it doesn’t do anything. For instance, if we have the following code:
x + 1;
Then it doesn’t do anything since we didn’t assign it to a variable and we didn’t return it in a function.
With build tools, expressions like these may be eliminated and break application logic.
Also, sequence assignment expressions like x = 1, y = 2
are always useless unless we return the values, assign them to another variable somewhere else, or do some manipulation with it later.
No Unused Labels
Unused labels are useless since they aren’t used anywhere. Therefore it’s dead code that’s just taking up space.
For instance, if we have the following:
loop:
for (let i = 1; i <= 5; i++) {
console.log(i);
}
Either we should use it or we should remove it. We can use it as follows, for example:
loop:
for (let i = 1; i <= 5; i++) {
console.log(i);
if (i === 2) {
break loop;
}
}
We break
the loop with the loop
label with break loop
when i
is 2.
No Unnecessary .call()
and .apply()
The call
and apply
method is only useful when we need to change the value of this
in a function and call it with various arguments.
The following uses for it aren’t very useful:
function greet(greeting) {
console.log(`${greeting} ${this.name}`);
}
greet.call(undefined, 'hi');
We passed in undefined
to make this
set to undefined
. So it’s the same as calling greet('hi')
directly.
Therefore, we don’t need to invoke the call
method.
Likewise, the following apply
call is also useless:
function greet(greeting) {
console.log(`${greeting} ${this.name}`);
}
greet.apply(undefined, ['hi']);
It’s also the calling greet('hi')
directly.
Instead, we should call greet
with call
or apply
in ways that are useful.
For instance, we should call them as follows:
function greet(greeting) {
console.log(`${greeting} ${this.name}`);
}
greet.apply({
name: 'jane'
}, ['hi']);
greet.call({
name: 'jane'
}, 'hi');
This way, we set the value of this
inside the function to an object with the name
property, so that this.name
inside the function can be populated with the this.name
.
We actually need to use call
and apply
to set the value of this
in the example above.
Conclusion
Unmodified loop conditions are bad most of the time because it may cause crashes because of the infinite loop.
However, infinite loops are useful in generator functions that keep returning values with the returned iterator.
Unused labels for loops are useless and so it’s dead code that should be removed.
call
and apply
that are useless, like those that set the value of this
to undefined
since they are no different than calling the function directly.
Finally, we also shouldn’t have unused expressions in our code since it’s just more useless code that we can remove.