Al Idian

Coercion in JavaScript

2017.04.02

Static vs dynamic typing

The difference between static typing and dynamic typing has to do with two things:

  1. When the type checking is done, and
  2. Whether variables can be assigned values of different types at run time.

Statically-typed languages determine variable type at compile time, and the type remains unchanged throughout the entire program execution. On the other hand, dynamically-typed languages have variables that are not associated with any particular type. Therefore, the types of values assigned are determined “on-the-fly” and can change during program execution.

Often, statically-typed languages require the programmer to indicate a variable’s type, while dynamically-typed languages do not. However, this is not always the case!

// Often, statically-typed languages require the programmer to indicate a variable's type...
string a = "foo";
// ...
while dynamically-typed languages do not.
var b = "foo";

Coercion in JavaScript

As a dynamically-typed language, allows variables to be assigned values of different types:

var b = "foo";      // b is assigned the string value foo
b = 15; // b is reassigned the numeric value 15
var c = true && b; // c is assigned the value 15

To support this, JavaScript relies on coercion, which means implicitly converting a variable’s type to another. For the unaware, coercion can cause some seemingly strange behaviour. In the highlighted line of the snippet above for instance, variable c is assigned the numeric value 15 because the operator && causes b to be evaluated to true (i.e. var c = true && true) — but then assigns the real value (before coercion) of the last operand to c.

Because JavaScript syntax is so close to that of Java (and C#, etc.), JavaScript developers coming from these languages are sometimes deceived into thinking the equality operator == in JavaScript is the same as that in Java. Because JavaScript coerces values, == in JavaScript is less stringent than in Java. For instance:

// Each of the following evaluates to true
var a = 1 == '1';
var b = false == 'false';
var c = 15 == '1' + 5;

In my opinion, === (or strict equality) should be used instead of == unless there is a specific reason to do otherwise. Unlike ==, === takes coercion out of the equation (punny!):

// Each of the following evaluates to false
var d = 1 === '1';
var e = false === 'false';
var f = 15 === '1' + 5;

Leveraging coercion

When used properly, coercion and == can allow developers to write some really clean and concise code. Note the example below:

var a, b, c;

...

// Method A
if (a === null || a === undefined) {
console.log("Hello world");
} else {
console.log(a);
}

// Method B
if (b == null) {
console.log("Hello world");
} else {
console.log(b);
}

// Method C
console.log(c || "Hello world");

Methods1 A, B, C all do the same thing but are written in order of conciseness. All three methods check whether a variable (a, b, or c) is null or undefined 2.

Method A is the clunkiest implementation. The strict equality is used to check that the variable is not strictly equal to null and not strictly equal to undefined.

Method B uses coercion and the == operator. Since the JavaScript engine coerces b to be equal to null even if its value is actually undefined, we can use this singular check to achieve the desired result.

Method C is the most elegant solution and also demonstrates knowledge of coercion. If c is either null or undefined, the alternate value “Hello world” is printed in its stead.

TL/DR

Understanding coercion (along with equality and strict equality in JavaScript) allows developers to avoid common pitfalls and write cleaner, more elegant code.

-----

Notes