Skip to the chapter
←JavaScriptGGroundworkJSJavaScript
JavaScript/Beginner/B8
8 / 41 written chapters
/

The cover
  1. B1Setup & mental model
  2. B2Execution context
  3. B3var, let & const
  4. B4Scope
  5. B5Single thread
  6. B6In the browser
  7. B7Types & values
  8. B8Strings & Math
  9. B9Operators & flow
  10. B10Functions
  11. B11Objects & arrays
  12. B12this
  13. B13Closures
  14. B14DOM & events
  15. B15Callbacks & promises
  16. B16Errors & tools
  17. B17Guided project
  18. ★Cheat page
  1. I1Scope & functions, properly
  2. I2Objects deeply
  3. I3Prototypes & OOP
  4. I4Async, properly
  5. I5Modules & tooling
  6. I6Regex & dates
  7. I7Error handling
  8. I8Real-time connections
  9. I9Offline & storage
  10. I10Browser APIs
  11. I11Modern JS
  12. ★Cheat page
  1. A1Engine & memory
  2. A2Advanced async
  3. A3Metaprogramming
  4. A4Types & data
  5. A5Patterns & architecture
  6. A6Performance
  7. A7Security
  8. A8Ecosystem
  9. A9Testing
  10. A10Observability
  11. A11Interview bank
  12. A12Build it yourself
  13. ★Cheat page

JSB8 · Part 1 · Beginner

Strings, numbers & Math

The everyday toolbox every other chapter quietly assumes you already have.

5 min read7 sections3 exercises
8 of 41

In this chapter

  • String methods beyond the basics
  • Case, and the string methods everyone assumes you know
  • Comparing text properly
  • Math — the methods that actually get used
  • A random integer in a range

and 2 more

about 5 min
07On this page
  1. String methods beyond the basics
  2. Case, and the string methods everyone assumes you know
  3. Comparing text properly
  4. Math — the methods that actually get used
  5. A random integer in a range
  6. Math.sign, Math.hypot, and checking a number is actually safe
  7. Formatting numbers for display

String methods beyond the basics

The types chapter already covered slice, trim, includes and split. These come up just as often and didn't fit there.

"Hello World".startsWith("Hello");     // true
"Hello World".endsWith("World");       // true
"Hello World".startsWith("World", 6);  // true — search starts at index 6, not the very start

"7".padStart(3, "0");                  // "007" — pad on the LEFT to a minimum length
"7".padEnd(3, ".");                    // "7.." — pad on the RIGHT

"ha".repeat(3);                         // "hahaha"

padStart is the standard fix for "always show two digits" — String(minutes).padStart(2, "0") turns 5 into "05" — without hand-rolling an if (x < 10) check.

Case, and the string methods everyone assumes you know

"Hello".toUpperCase();      // "HELLO"
"Hello".toLowerCase();      // "hello"

"Hello".at(-1);              // "o" — negative indices count from the end, same idea as array .at()
"Hello"[-1];                  // undefined — plain bracket access does NOT support negative indices

.at() exists on strings for exactly the reason it exists on arrays: str[str.length - 1] for "the last character" works, but it's a mouthful next to str.at(-1), and plain bracket indexing has no concept of counting from the end at all — it just returns undefined for any negative index.

⚠ toUpperCase/toLowerCase are not always safe for comparison A handful of characters change length when case-folded — the German ß becomes "SS" under .toUpperCase(). Comparing user input case-insensitively is usually safer with a.localeCompare(b, undefined, { sensitivity: "base" }), covered next, than with a manual .toLowerCase() === .toLowerCase().

Comparing text properly

console.log(["résumé", "resume", "zebra"].sort());
console.log(["résumé", "resume", "zebra"].sort((a, b) => a.localeCompare(b)));

A plain .sort() with no comparator compares strings by raw UTF-16 code unit — accented characters and non-Latin scripts routinely land in the wrong place. localeCompare sorts the way a human reading that language actually expects, and takes an optional locale and options argument (a.localeCompare(b, "en", { sensitivity: "base" })) for case-insensitive, accent-insensitive comparison in one call instead of lowercasing both sides by hand.

Math — the methods that actually get used

CallDoes
Math.round(x)nearest integer — .5 rounds up
Math.floor(x)rounds down, always — toward negative infinity
Math.ceil(x)rounds up, always
Math.trunc(x)drops the decimal part — rounds toward zero
Math.abs(x)absolute value
Math.min(...) / Math.max(...)smallest/largest of the arguments — not an array; spread one in
Math.random()a float, from 0 up to (never including) 1
console.log(Math.floor(-4.5));
console.log(Math.trunc(-4.5));

-5, then -4 — the difference only shows up on negative numbers. floor always moves toward negative infinity; trunc always moves toward zero. Reaching for the wrong one is a real, if rare, off-by-one source once negative values are involved.

A random integer in a range

function randomInt(min, max) {                 // inclusive of both min and max
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
randomInt(1, 6);   // a dice roll — 1 through 6, inclusive

Math.random() alone gives a float between 0 and just under 1 — never useful on its own. Multiplying by the size of the range and flooring turns that float into one of exactly max - min + 1 whole numbers; the final + min shifts the whole range to start at the right place instead of at 0. This exact formula is worth memorizing — it gets asked for cold often enough that deriving it live, under pressure, is its own small trap.

Dry run: randomInt(1, 6) for four sample Math.random() values

Math.random() returns× (max − min + 1) = × 6Math.floor(...)+ min (1)Result
000+11
0.166...0.996...0+11
0.53.03+14
0.9999995.9999945+16

Math.random() gets arbitrarily close to 1 but never reaches it, so Math.floor(random * 6) only ever lands on 0 through 5 — six whole numbers — and + min shifts that range to land on 1 through 6. Drop the + 1 inside the multiply and 6 becomes unreachable; drop the Math.floor and almost every roll is a decimal.

Math.sign, Math.hypot, and checking a number is actually safe

Math.sign(-5);    // -1
Math.sign(0);     // 0
Math.sign(7);     // 1

Math.hypot(3, 4);   // 5 — the hypotenuse: sqrt(3**2 + 4**2), without writing the formula out

Math.sign is the direct answer to "is this positive, negative, or zero" without a chain of > 0 / < 0 comparisons. Math.hypot shows up constantly in anything involving distance — two points on a canvas, a drag gesture's total movement — as the built-in alternative to Math.sqrt(a ** 2 + b ** 2).

console.log(Number.isInteger(5), Number.isInteger(5.5), Number.isInteger("5"));
console.log(isFinite("123"), Number.isFinite("123"));

true false false, then true false. The global isFinite/isNaN coerce their argument to a number first — "123" passes. The Number. versions refuse to coerce at all: a string is never a number to Number.isInteger or Number.isFinite, full stop, no matter what it contains. The Number. versions are the safer default for exactly that reason — they answer "is this actually a number with this property," not "would this convert into one."

Number.isSafeInteger(n) goes one step further, checking against the exact-representable limit covered in Types & data — useful the moment a value might have come from parsing JSON that originated outside JavaScript, where a huge integer id can silently lose precision on the way in.

Formatting numbers for display

(1234.5).toFixed(2);                 // "1234.50" — a STRING, fixed decimal places, no thousands separator
(1234.5).toLocaleString("en-IN");    // "1,234.5" — locale-correct digit grouping
(1234.5).toLocaleString("en-IN", { style: "currency", currency: "INR" });
// "₹1,234.50"
⚠ toFixed rounds, and always returns a string (1.005).toFixed(2) is "1.00", not "1.01" — the same floating-point imprecision from the types chapter means 1.005 isn't quite exactly representable to begin with. And the return value is always a string — (5).toFixed(2) + 1 is "5.001", concatenation, not addition, unless it's converted back with Number(...) first.

toFixed and toLocaleString solve different problems: toFixed guarantees an exact number of decimal places with no locale awareness at all; toLocaleString formats for a specific reader's language and region (digit grouping, currency symbol placement) but won't force a fixed decimal count unless told to. For money specifically, Intl.NumberFormat (covered in Regex & dates) is the same formatting engine toLocaleString calls internally — worth reaching for directly when formatting many values with the same options at once.

Interview answer, one sentence

"Strings are immutable UTF-16 sequences, so their methods return new strings; numbers are IEEE 754 doubles, so 0.1 + 0.2 is not 0.3 and money belongs in integers; and Intl formats numbers, dates and currency for the user's locale without hand-rolled code."

Before you move on
  • Write String(minutes).padStart(2, "0") from memory, and explain what problem it solves.
  • Explain why Math.floor(-4.5) and Math.trunc(-4.5) give different answers, and state the rule each one follows.
  • Derive the randomInt(min, max) formula from scratch, and say what breaks if you drop the + 1 or the Math.floor.
  • Explain why Number.isInteger("5") is false while the global isFinite("123") is true — what's different about how each one treats a string.
  • Explain why (1.005).toFixed(2) is "1.00", and why the return value is always a string.

03Practice this chapter

Opens in the editor: write it, run it, and check it against real tests.

  • 10 testsFormat seconds as MM:SSbeginner
  • 9 testsA random integer, inclusive on both endsbeginner
  • 9 testsFormat a price for displaybeginner
All 35 for this level →
B8

Finished reading?

0 of 41 chapters read in this series

→Next stop

  1. B7Previous · B7Types & values
  2. B8you are here
  3. Next · B9Operators & flowEvery operator here has an interview question hiding behind it.11 min read

01On this page

7 sections · 0%

  1. 01String methods beyond the basics
  2. 02Case, and the string methods everyone assumes you know
  3. 03Comparing text properly
  4. 04Math — the methods that actually get used
  5. 05A random integer in a range
  6. 06Math.sign, Math.hypot, and checking a number is actually safe
  7. 07Formatting numbers for display

[] chapters · t top