Eye Training · Values, Equality and Numbers
JavaScript converts values quietly. Every bug here is a value that was quietly converted into something else.
Part 2 · Surface 19. Bug counts are hidden and some snippets are clean. See Start Here for how to use these drills.
J · The basics
Bug hunt
J · Retry option
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Order total
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Check the score
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · List the fields
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
J · Missing value
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
M · Three years in, these should jump out
Bug hunt
M · Invoice line
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Age field
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Add tax
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Force update
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Feature flag
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Validate quantity
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
M · Money in paise
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
S · Where seniors stand out
Bug hunt
S · Tweet ids
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
S · Unix timestamp
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
Bug hunt
S · Highest bid
Bug count hidden, and some snippets are clean. Click every line you think is wrong (or none), then check.
0:00 / 1 min
What your eye checks
Whenever a value is compared, defaulted, converted or used in arithmetic, ask:
- Which falsy values are valid here?
0,''andfalseare often real values.||andif (!x)throw them away;??and== nulldon't. - What type is it really? Form fields, query strings, environment variables and headers are strings.
+concatenates strings. - What does the conversion do with odd input?
Number('')is 0,Number('12px')isNaN,parseInt('12px')is 12, globalisNaNconverts first. - Is it money? Integers in the smallest unit, or a decimal library. Never floats; never
toFixeduntil display. - Is
NaNchecked withNumber.isNaN? And isnullexcluded beforetypeof x === 'object'? - Are numbers or versions compared as strings?
- Can it exceed the safe range? 64-bit ids beyond 2⁵³ − 1; bitwise operators truncate to 32 bits.
- What does the empty case return?
Math.max(),Math.min(), averages of nothing (0 / 0isNaN).
Tells
| You see | Ask |
|---|---|
x || default | Can x legitimately be 0, '' or false? |
input.value + … | String or number? |
=== NaN | Always false. |
typeof x === 'object' | What about null? Arrays? |
price * qty with decimals | Money as floats? |
Number(field) then a NaN check | What about an empty field? |
.toFixed( followed by + | It's a string now. |
version < '…' | Comparing strings? |
process.env.X used as a boolean | "false" is truthy. |
isNaN( without Number. | It converts first. |
An id field parsed from JSON | Bigger than 2⁵³? |
| 0 or ~~ | Over 2³¹? |
Math.max(...list) | Empty list? Huge list? |
Go deeper
- L1–L2 · Logic and TypeScript: the same slips in bigger files, and where TypeScript does and doesn't catch them
- Previous surface: Shared state and races · Next: Objects and arrays