Back in my early days of writing JavaScript, coercion bit me more times than I care to admit. Not the trivia kind you see in interview questions. The real kind, where a value quietly is not the type you thought it was and your code does the wrong thing without throwing a single error. No red text, no crash, just wrong.
The whole thing is one idea: JavaScript converts types for you, silently, whenever an operator wants a different type than the one it got. Once you know the two rules below, most of the weirdness stops being weird.
The plus sign picks a side
If either side of + is a string, JavaScript turns the other side into a string too and concatenates. Otherwise it turns both into numbers and adds. That is the entire rule, and it explains the classics:
plus-coercion.js
"5" + 3 // "53" (string wins, 3 becomes "3")
"5" - 3 // 2 (minus has no string mode, always numbers)
[] + [] // "" (both arrays become empty strings)
[] + {} // "[object Object]"
The famous one, + [], equals 0 for a sillier reason: at the start of a statement JavaScript reads `as an empty code block, not an object, so what is left is+[], unary plus on an empty array, which coerces to0`. Wrap it in parentheses and it behaves like you expected.
== is the real trap, === is the fix
Loose equality converts both sides until they match, and the conversion table is not what you would guess:
loose-equality.js
`javascript
"" == 0 // true
"0" == false // true
null == undefined // true
null == 0 // false (yes, really)
`
The fix is boring and it works: use ===, which checks the type first and never converts anything. If the types do not match, the answer is false, full stop. I have not written == on purpose in years.
Where this bites you in real code
The trivia is fun, but here is where it actually costs you. Form inputs are always strings, so input.value + 1 concatenates instead of adding. An API sends a number back as a string and your total is suddenly "10050" instead of 150. A check like if (count) skips 0 because 0 is falsy, and an empty string is falsy too. None of these throw. They just quietly do the wrong thing, and you find out from a user, not from your console.
The habit that saves me: convert on purpose, at the boundary. Number(input.value) the second a value enters your code, and === everywhere after that. If a conversion is explicit, it cannot surprise you.
Try it live
Tap any of these and see what JavaScript actually does with it. Guess first, it is more fun that way:
Live: coercion playground
Try it live on nayemalam.com.
So, what have I learnt?
-
+concatenates if either side is a string, adds if both are numbers. That one rule explains most of the classics. -
==converts until both sides match, and the conversion table is not guessable.===never converts, so use it. - The bugs that cost real time are never the trivia ones. They are a string where a number should be, found by a user instead of an error.
- Convert on purpose at the boundary (
Number(),String()), and the surprises mostly disappear. -
typeofis your friend when a value is misbehaving. Check the type before you blame the logic.
Originally posted on nayemalam.com/blog.
Top comments (0)