Is JavaScript Trash? — Part 1: Types

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.

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 a problematic
  • The 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”). The compiler figures out the types at run time. Many multifaceted developers 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.

But let’s be clear the above does not entirely apply to modern JavaScript compilers. JavaScript engines are savage (good kind of savage), they will take a previously ran function and optimise it either by baseline compilation or JIT as well as a handful of other master mind 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 for each loop, so it’s super fast. Hopefully this clears up any 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.

  • Learn JavaScript data types and data structures.
  • Use ES6+.
  • Use Array.isArray to check array types.
  • Use Object.is to compares primitive types where typeof and === are not sufficient. E.g. Object.is(someNumber, NaN) determines if a number is Not A Number.
  • 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.
  • Only use the typeof operator for primitive types. (e.g. Not for arrays, objects, blobs) with the exception of null, don’t use it for that…
  • typeof null // “object” is a mistake in the language you could use Object.is(someNumber, null) or convert the value to a string.
  • instanceof is not a reliable type checker.
  • 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 a type.

({}) 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:

Some random graph that kind of fits my hypothesis, 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.

(Feel free to pull me up on anything I should re-evaluate, I’m not claiming to be an expert)

In part 2 I will discuss coercion, thanks for the read ;-)