chapter four

4 Primitives, Coercion, and Equality

 

This chapter covers

  • Distinguishing between JavaScript’s two representations of nothing: undefined and null
  • Understanding why some JavaScript values are considered falsy
  • Using symbols to provide guaranteed-unique property keys that prevent naming collisions
  • Recognizing where type coercion happens automatically in arithmetic, comparisons, and logical operations
  • Choosing between loose equality with its multiple conversions and strict equality that never coerces
  • Preventing performance degradation from repeated type coercion in loops and sort functions
  • Exploring how V8 optimizes primitives through pointer tagging for zero-allocation storage

Here's a fun bug: a payment system starts double-charging customers because someone wrote if (!transactionId) to decide whether a charge had already been recorded, and the earliest rows in the legacy table were numbered from zero. Zero is falsy, so the check reads "already charged" as "never charged" and runs the charge a second time.

These types of bugs happen all the time. Not because developers are careless, but because JavaScript’s type system is… well, let’s say “quirky”. The same flexibility that lets you prototype quickly with no type declarations, automatic conversions, and forgiving comparisons, also sets traps that will not be noticeable until production.

Let’s consider a simple example that contains three different bugs:

4.1 JavaScript’s two kinds of nothing

4.2 Booleans and Truthiness

4.2.1 Falsy vs. Truthy

4.2.2 Boolean operators and short-circuit logic

4.3 Symbols

4.3.1 How symbols differ from other primitives

4.3.2 The Global Symbol Registry

4.3.3 Memory considerations

4.4 Type coercion

4.4.1 The coercion problem in practice

4.4.2 When JavaScript coerces types

4.4.3 The three essential conversions

4.4.4 The performance cost

4.4.5 The specifications conversion operations

4.5 Type comparisons

4.5.1 Loose equality vs Strict equality

4.5.2 The comparison operators

4.6 Summary