What I don't like in JavaScript

Published on

I actually love JavaScript and despite of its flaws I think it's still has done a lot of things right and it's one of the best programming languages in the world despite of the criticism.

Here are some of the best virtues of JavaScript:

So what I don't like in JavaScript?

That being said, JavaScript has its fair share of design flaws, quirks and inconsistencies which can be very annoying and most of them are here to stay. Many people think the main problems are from type coercion (or casting). I think this is not the biggest problem because you can easily avoid them most of the time with the right habits. IMHO many of this type coercion quirks are kind of artificial and, especially with the right habits, it's unlikely to accidentally use them. But it's definitely a footgun too. Anyways, let's start the list of things that I don't like in JavaScript.

Typeof & Instanceof

typeof and instanceof are 2 related operators which are, sadly, confused and this is a source for many mistakes and bugs.

typeof val returns the fundamental type of the val as a string. Here are the values that typeof val can return:

  1. "undefined"
  2. "boolean"
  3. "number"
  4. "string"
  5. "bigint"
  6. "symbol"
  7. "object"
  8. "function"

val instanceof ClassName returns boolean indicating that val is an instance or a derivative of class ClassName.

Typeof null

JavaScript has 9 fundamental value types, which are:

  1. Null
  2. Undefined
  3. Boolean
  4. Number
  5. String
  6. Bigint
  7. Symbol
  8. Object
  9. Function

The problem is that for null typeof null will return "object" instead of "null". This is because in the first implementation of JavaScript null was treated like a reference to an object, and, unfortunately, this cannot be fixed now because this will break the backward compatibility and a lot of code that depends on this quirk.

Comparing 2 NaN numbers

Another annoying thing, although not only specific to JavaScript, is comparing 2 NaN values. In JavaScript you can compare 2 primitive values with the === or == operator, with the only exception of NaN. Yes, NaN === NaN will yield false. This is quite an inconvenience, this means that NaN should be handled in a special way. The only working ways for comparing 2 NaN values are:

Actually, this one is not so much JavaScript's fault. It's because of the IEEE standard for floating point numbers, and other languages have a similar problem.

The default comparator of Array.prototype.sort()

By default Array.prototype.sort() sorts lexicographically instead of simply comparing the elements. This means that if you sort numbers without providing a custom callback you might think that the sorting worked correctly:

console.log([4, 2, 6, 1, 7, 9, 5, 8, 3].sort()); // [1, 2, 3, 4, 5, 6, 7, 8, 9], seems correct console.log([4, 2, 10, 6, 1, 7, 9, 5, 8, 3].sort()); // [1, 10, 2, 3, 4, 5, 6, 7, 8, 9], what?

So instead you mast pass a callback:

console.log([4, 2, 10, 6, 1, 7, 9, 5, 8, 3].sort((a, b) => a - b)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Sensitivity to new lines

JavaScript is designed to work even if you don't write semicolons (;) after the statements. This works most of the time pretty well. However, this causes some unexpected side effects which might be very hard to debug if you are not familiar with this feature. For example, look at this function:

function sum(a, b) { return a + b; } console.log(sum(10, 20)); // undefined

The function will return undefined instead of 30. The reason is because new lines are treated as statement separator tokens like semicolons are and the last statement will be return.

So in order to make the function return the correct value we must be careful with the formatting:

function sum(a, b) { return a + b; } console.log(sum(10, 20)); // 30

Accidentally declaring a global variable

In JavaScript if you forget to to add var, let or const in the variable declaration, the variable might be created globally without causing any exception:

function f() { someVar = 5; // no exception } f(); console.log(someVar); // 5

Fortunately, this doesn't happen in strict mode and since the code in classes or modules is in strict mode, this mistake will cause an exception.

Octal numbers

If a number contains the digits 0-7 and has a leading 0, it is interpreted in base eight and not base ten:

console.log(0708); // 708 console.log(0707); // 455, 707 in octal is 455 in decimal

Array constructor

The array constructor has very different behaviors depending on the number of arguments:

console.log(new Array()); // [] console.log(new Array(3)); // [undefined, undefined, undefined] console.log(new Array(3, 4 ,5)); // [3, 4, 5]




Read previous