Coercion in JavaScript
2017-04-02
Static vs dynamic typing
The difference between static typing and dynamic typing has to do with two things:
- When the type checking is done, and
- 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.
Summary
Understanding coercion (along with equality and strict equality in JavaScript) allows developers to avoid common pitfalls and write cleaner, more elegant code.
-----
Notes
- 1 To be clear, the word method is not used in the object-oriented sense here.
- 2 In JavaScript, null and undefined are two distinct primitive values. null connotes an intentional lack of value, while undefined means a value was never set.