The Dom Boundary And Automatic Coercion

Type coercion is not a mistake: it's a design feature built for the flexibility of the web browser.

April 25, 20264 min read1 / 5

Now that we've seen how closure allows our functions to keep their memories, we're ready to tackle the "dark side" of JavaScript. Its type coercion is often called "notorious" or "infamous," but it's actually an incredibly powerful system designed to be flexible.

JavaScript doesn't run in isolation; it runs in a web browser. In the early days, its designers thought, "Let's be helpful here and coerce data types to make them usable immediately."

The Essentials

  1. Operators as Action Dispatchers: Operators like * or + aren't just symbols; they kick off actions (like multiplication or coercion) based on the operands adjacent to them.
  2. The DOM Boundary: Data flying from the webpage (DOM) into JavaScript almost always arrives as a string, even if the user typed a number.
  3. Coercion Funnels: JavaScript uses three major funnels to convert data: toNumber, toString, and toBoolean.

The Webpage Boundary

Imagine we're building a product page. We have a price of 7 and a quantity that the user enters into a form.

JavaScript
let price = 7; let quantity = "3"; // Comes from the DOM as a string let total = price * quantity;

In any other language, multiplying a number by a string (a letter "3") would be an error. You can't multiply a number by a letter. But JavaScript's designers wanted to make the interface between the DOM and the runtime less strenuous.

The toNumber Funnel

As soon as the multiplication operator (*) sees a number on one side and a string on the other, it kicks off type coercion. It hits the string with a toNumber conversion, turning the string "3" into the number 3.

JavaScript Execution Engine
Thread of Execution
1let price = 7;
2let quantity = "3";
3let total = price * quantity;

Step 1:Global memory stores the number 7.

Memory
price7
Call Stack
Global
Bottom of Stack

The "Mortifying" Result: The + Operator

While most math operators (-, *, /) always kick off toNumber, the addition operator (+) is a bit of a "trickster."

If you have a donation of "10" (from a string) and you try to add it to your total of 21:

JavaScript
let total = 21; let donation = "10"; let grandTotal = total + donation; // "2110"

Because one side of the + is a string, JavaScript kicks off the toString funnel instead of toNumber. It converts the number 21 into the string "21", and then concatenates the two strings.

The result is "2110". This is a fairly mortifying result that gives programming languages a bad name, but it's a consequence of the design decision to favor string concatenation when a string is present.

Taking Manual Control

To avoid these unpredictable automated behaviors, pro-code developers take manual control of coercion. Instead of letting the operator decide, we manually trigger the conversion:

  • Unary Plus: +quantity manually kicks off toNumber.
  • Number Function: Number(quantity) manually kicks off toNumber.
  • Template Literals: `${total}` manually kicks off toString.

By being explicit at the browser boundary, we ensure our code remains predictable and bug-resistant.

In the next part, we'll look at the "comparison problem" and why identical-looking objects can be so hard to match.

Further Reading and Watching