ESC

Type to search the knowledge base.

Numeric Separators

Use underscore separators in numeric literals for readability — rules, bases, BigInt, and what they do not change at runtime.

beginner3 min read
  • javascript
  • numeric-separators

Long numeric literals are hard to scan. Numeric separators let you put _ inside number literals. They are syntax sugar only — the value is identical to the unadorned number.

const budget = 1_000_000;
const budget2 = 1000000;
budget === budget2; // true

const mask = 0xFF_FF_FF_FF;
const bits = 0b1111_0000_1111_0000;
const dec = 1_234.56_78;
const big = 9_007_199_254_740_991n;

Rules (what parsers reject)

// Invalid:
// 100_          trailing
// _100          leading
// 1__000        double
// 1_e2 / 1e_2   next to e in scientific in illegal positions
// 0x_1          right after base prefix sometimes restricted — avoid edge forms

Safe habit: group like humans do — thousands for decimal (1_000_000), nibbles/bytes for hex/binary (0xFF_EC).

Not for strings or runtime formatting

Number('1_000'); // NaN — separators are NOT in string-to-number
parseInt('1_000', 10); // 1 — stops at _

Intl / toLocaleString format output for display; separators are for source code.

(1_000_000).toLocaleString('en-US'); // "1,000,000"

Where they shine

Use Example
Timeouts 30_000 ms
Limits maxSize = 5_242_880 (5 MiB)
Bit patterns 0b1100_1010
BigInt IDs in tests 123_456_789_012_345n

Engines and tooling

Supported in modern browsers and Node. If you target ancient environments without a transpile step, avoid them — but any current frontend toolchain is fine.

They don’t appear in JSON (JSON has no underscores in numbers). Don’t expect wire formats to accept them.

Interview angle

There’s little “algorithm” here — interviewers may ask whether 1_000 === 1000 (yes) or whether parseInt('1_000') works (no). Knowing the compile-time only nature separates people who skimmed the feature from people who used it.

Interview answer (out loud)

“Numeric separators let underscores appear in number literals for readability. They’re erased at parse time, so the runtime value matches the same digits without underscores. They don’t work inside numeric strings for Number/parseInt, and JSON doesn’t support them.”

Bases and separators together

const permissions = 0b1100_0001;
const color = 0xff_cc_00;
const size = 0o755; // octal still valid; separators: 0o7_5_5

// Exponent form
const approx = 1.2e6;
const approxSep = 1_200_000; // often clearer than e-notation for configs

Team style guides sometimes require separators only above 4 digits (1000 vs 1_000) so files don’t look noisy.

Linters and formatters

Prettier leaves numeric separators alone (they’re author intent). ESLint plugins can require them for large literals — optional. What matters: don’t reformat away meaning in code review bikesheds; separators never change runtime.

Interview micro-drills

Number('1_000');           // NaN
eval('1_000');             // 1000 — parses as source
JSON.parse('{"n":1_000}'); // throws — JSON grammar has no _

Knowing the boundary between language syntax and data formats is the actual skill.

Readability conventions

Group decimal literals in thousands (1_000_000) and binary/hex in nibbles or bytes (0b1111_0000). Stay consistent within a file so reviewers scan numbers quickly during production incidents.

Further reading

Related guides