JavaScript: Poorly Designed? — Part 1: Types

Julien Etienne
5 min readFeb 12, 2018

--

article.addEventListener(“click”, bait, true);

I think it’s fair to say that JavaScript is conceivably the most misunderstood programming language despite being so widely consumed. So how is it being misunderstood, well apparently from what I’ve heard…

  • JavaScript was poorly designed.
  • It’s a broken language.
  • This is why we have supersets like TypeScript and PureScript that make it bearable.
  • Libraries like React fix the crappy JS DOM interface that is so cumbersome.
  • There’s a short book called “JavaScript The Good Parts” so it clearly must have a lot of bad parts.
  • Back-end devs laugh at JavaScript because of all the problems they encounter compared to real programming languages like Java and c++.
  • JavaScript is slow.
  • It’s not a proper OOP language.
  • From the comments: “ITS STILL GARBAGE YOU NOBOS LENAR TO WRTIRE”

You may be wondering wow is any of this true, let’s find out.

A Broken Language?

What do they mean when they say “broken”? What they’re referring to is:

  • Dynamic types
  • Object Wrappers
  • Coercion
  • Old things people still believe are problematic
  • IEEE 754 Double Precision numbers
  • Pseudo classical OOP programming

There are a tonne of quirks and misconceptions within the language. Through out these articles I will try to cover the ones that you are bound to come across at work, on social media or surprisingly by experienced software developers.

Dynamic Types

JavaScript is a dynamically typed language (or has “no static types”). Types are handled at run time. It’s common for multifaceted developers to despise this because:

  • Types are define before run-time in statically typed languages thus being faster for the compiler.
  • Statically typed languages are “supposedly” less error prone.

The above does not entirely apply to modern JavaScript compilers. JavaScript engines are savage (good kind of savage), for instance they will take a previously ran function and optimise it either by baseline compilation or JIT as well as a handful of other optimisations.

V8 doesn’t produce bytecode or any intermediate code

In short this means your JS animation loop will be optimised within in the browser rather than being interpreted on the fly per call, so it’s super fast. Hopefully this clears up exaggerations of JS types being extremely slow.

Some people get frustrated working with JavaScript types, this is commonly due to:

  • A lacking JavaScript type knowledge
  • Poor type management

Or both, usually both.

Here’s a comprehensive list of tips to manage types the easy way without TypeScript, Flow, PureScript or whatever.

  • Read up on JavaScript data types and data structures.
  • Use ES6+.
  • Use Array.isArray to check array types.
  • Use Object.is to compare primitive types where typeof and === are not sufficient. E.g. Object.is(someNumber, NaN) determines if a number is Not A Number.
  • As mentioned in the comments a cleaner way to check numeric numbers would be vai Number.isFinite(value)
  • Understand that NaN is a type of number, therefore avoid the use of isNaN.
  • The new operator will purposely create an Object Wrapper for types such as Boolean() & String(). Without the operator you are just creating a type value. Object wrappers are very useful.
  • typeof null // “object” is a mistake in the language you could use Object.is(someNumber, null), convert the value to a string or detect it’s class (see below).
  • instanceof is not a reliable for type checking.
  • Use ({}).toString.call() where typeof is not sufficient.
  • Always use typeof where reliable.

Let me explain the second to last bullet:

Everything in JavaScript is an object, that’s the beauty of JavaScript.

Because “almost” everything in the language spawns from Object, everything is like Lego. The aforementioned is the same as each:

Each native object in JavaScript has an internal [[class]] that can only be accessed using variants of Object.prototype.toString to obtains the below:

As you can see we must set the context of this via call or apply.

It’s important to understand here that you are returning a [[class]] and not a type, fortunately native data type classes are equal to their type names. HTMLBodyElement being the class of document.body is an example of the difference between a [[class]] vs it’s type “Object”.

({}) is just a way to evaluate Object for dot notation. Alternatively we could have stored {} as a variable to achieve the same thing.

Quick Recap:

  1. Favour === and typeof first.

2. Where they are not sufficient use Object.is for primitive comparisons.

3. Let Array.isArray do it’s job.

4. And for everything else fall back to: ({}).toString.call().

Quick plug: Here’s Typecase a lightweight type checker.

You can do all of the above and still build a hard to maintain monstrosity. To prevent your functions working like trash follow the conventions of pure functions where possible and think of your code as a chain of reactions:

This kind of fits my explanation, work with me here!

If each circle is a deciding function, and each line is a connecting function the connecting fn should only accept one type and return one type.

You won’t need to intentionally type check any deciding fn except maybe the initial fn since the connecting fns will do all the type-checking. And of course you’re unit testing ( wink wink).

Of course this diagram does not represent how most programs are structured. The point is that:

you don’t need to explicitly type check every function in JavaScript if you are breaking down the responsibilities of each constituent.

You can type check receiving arguments and/ or return statements within a function, depending on the feasibility. Type management is generally down to practice and discretion, grasping JS types will help massively.

Conclusion

So this article was basically a tiny bit click-baity and hopefully a little bit demystifying for anyone who has a stubborn notion that JavaScript types are a mess or difficult to get your head around.

Next up: JavaScript: Poorly Designed? — Part 2: Coercion

Thanks for the read ;-)

--

--