JavaScript: Poorly Designed? — Part 2: Coercion

Julien Etienne
4 min readFeb 26, 2018

--

Work you f@£$ %$£ “££* $cript!

— Following up from: JavaScript: Poorly Designed? — Part 1: Types

Let’s look at some common opinions by well rounded developers on coercion:

  • It’s is a mistake.
  • It’s an unpredictable behaviour.
  • It’s a horribly obscure way to do a type conversion. — Stack Overflow
  • There’s just no way to handle certain types.
  • JavaScript has problems adding numbers (Wrong topic Einstein).
  • It’s slow at run time.

…(Eats popcorn)

In Part 1 we looked at types and hopefully demystified some of the major misconceptions as well as offering a few tips that are not preached enough in front-end development. So let’s explore coercion…

Type Conversion, Type Casting and Type Coercion

These terms do not always refer to the same thing, different families of languages refer to either as implicit, explicit, compilation changes or a loss of precision/ truncation.

In JavaScript the word coercion is generally used to represent implicit conversions at run time. That’s generally how I’m going to refer to coercion throughout this article.

What is coercion?

Fig 1

That’s coercion in a nutshell. To fully understand coercion rules check out MDN’s Equality comparisons and sameness or JavaScript coercion rules. As you can see from these sources coercion is an intentional behaviour that can easily trip up someone coming from a more traditional language.

Coercion is a feature of the language

There are three types of coercion in JavaScript:

  • toString
  • toBoolean
  • toNumber

Each can be utilised when using an operator i.e. + with operands i.e. 1, true of different types. They are the essence of JavaScript, every time you use a template literal you are performing toString coercion.

In fig 1 we add 1 to true. JavaScript follows a rule which converts a boolean to a number for this combination of operand types. False is represented as 0 and true is represented as 1, hence the value evaluating to 2.

The benefits of coercion?

This is probably not the most interesting example but let’s look at how a “real” language handles converting a float to a string:

Java:

In JavaScript you could do either since it is an object-based language.

Each solution is not the same. For instance toString will throw an error for null or undefined but this may not be important if you have previously secured the value’s type. It’s not about preference it’s about what fits best for the end result.

Some things to consider about coercion, it:

  • Can somewhat use less code (trivial benefit).
  • Can be exploited for minification (A useful factor).
  • Can sometimes perform minimal operations (Just converts and nothing else).
  • Can be ideal if you have previously type-checked both operands.

Here’s a number and boolean example of coercion:

Remove decimals:

Approximately invert a number and remove its decimals:

Coerce a value to a boolean

Common misunderstandings of coercion?

You can’t just write anything and expect magic. In the below example, the number takes precedence over the string as multiply has no ability to concatenate. Therefore the string is coerced to NaN as it has no numeric representation (NaN is technically a number in the world of JS).

There is no need to memorise every type conversion. Instead:

  • RTMFM when you need to.
  • Type-check and use the internal type checker: See examples in part 1
  • Stop using == where you should be using === (Double equals is not faster)
  • Type-check where you can possibly receive a range of types or before returning a range of types.
  • Do not use isNaN
  • Do not directly compare values to NaN
  • Do not “solely” typeof check numbers since NaN is a number unless you want NaN which means you need to see a doctor immediately.
  • Do not rely on coercion by negligence…

Although it may be tempting, it’s not wise to rely on coercion, especially by assuming values you may receive.

Let’s say we do:

If value is null or undefined you expect it to return false. But what if it’s 0? or an empty string ? These are extremely common pitfalls for newbies using JavaScript, which can easily makes them believe it’s a bad language.

How, where and when not to use coercion

Always imagine that coercion is not your friend until you need a favour:

Here we avoid coercion

Let’s say for some reason we want a value that is not empty, not zero, not false, not null, not undefined or NaN.

Didn’t I just say not to do this? This is because those 6 conditions are rarely needed and are commonly problematic in most medium/ large code bases. Only use this if you know what you’re doing.

But it’s slow at run time?

This has been debunked in part 1. In several cases coercion out performs native methods, but this should not be a factor in your decision to use either.

Conclusion

Let’s look back at some of the things I’ve heard about this topic

  • It’s is a mistake: ✘
  • It’s an unpredictable behaviour: ✘ (RTMFM)
  • It’s a horribly obscure way to do a type conversion: (Some people hate cheese)
  • There’s no way to handle certain types: ✘ (If you are treating JS like a statically typed language then no shit Sherlock)
  • It’s slow at run time: ✘

There are mistakes in JavaScript, like every language but if you embrace JS for it’s strengths you will rarely encounter any. The majority of JavaScript mistakes shared around social media and ridiculed are not actual mistakes, they are mostly representations of people’s misunderstandings due to the masses of mis-leading articles and opinions out there. Let’s not become part of the problem.

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

Next up: JavaScript: Poorly Designed? — Part 3: IEEE 754

I discuss floating point precision. Thanks for the read ;-)

--

--