The proposal “Numeric Separators” by Sam Goto and Rick Waldron is currently at stage 3. This blog post explains how it works.

What are numeric literals? #

JavaScript has several numeric literals:

Decimal literals: 123.45 , 86 , 12e-5

, , Binary integer literals: 0b1011

Octal integer literals: 0o765

Hexadecimal integer literals: 0x2FF

Interestingly, unary minus ( - ) is an operator and not part of numeric literals (apart from signed exponents in decimal literals).

Grouping digits in numeric literals #

Grouping digits to make long numbers more readable has a long tradition. For example:

At the end of 2016, Munich has 1,464,301 inhabitants.

The distance between Earth and Sun is 149,600,000 km.

The proposal allows underscores as separators in numeric literals:

const inhabitantsOfMunich = 1 _464_301; const distanceEarthSunInKm = 149 _600_000;

With other bases, grouping is important, too:

const fileSystemPermission = 0b111 _111_000; const bytes = 0b1111 _10101011_11110000_00001101; const words = 0xFAB _F00D;

You can also use the separator in fractions and exponents:

const massOfElectronInKg = 9.109 _383_56e -31 ; const trillionInShortScale = 1e1 _2;

The key restriction to keep in mind is: You can only put underscores between two digits. Therefore, the following numeric literals are illegal.

3 _ .141 3. _141 1 _e12 1 e_12 _1464301 1464301 _ 0 _b111111000 0 b_111111000

Furthermore, you can never use more than one underscore in a row:

123 __456

The motivation behind these restrictions is to keep things simple.

BigInts and numeric separators #

The proposed arbitrary-precision integers (BigInts) enable you to represent larger numbers numerically. Thus, numeric separators are especially helpful with them:

const massOfEarthInKg = 6 _000_000_000_000_000_000_000_000n;

BigInts are often used to represent money in the financial technical sector. Separators can help here, too:

const priceInCents = 123 _000_00;

Parsing numbers with separators #

The following functions for parsing numbers will not support separators:

Number()

parseInt()

parseFloat()

For example:

> Number('123_456') NaN > parseInt('123_456') 123

The rationale is that numeric separators are for code. Other kinds of input should be processed differently.

A helper function for parsing numbers with separators #

One technique for parsing numbers with separators is to remove non-digit characters:

const RE_NON_DIGIT = /[^0-9]/gu ; function removeNonDigits ( str ) { str = str.replace(RE_NON_DIGIT, '' ); return Number (str); }

This is how you use this function:

> removeNonDigits('149,600,000') 149600000 > removeNonDigits('1,407,836') 1407836

Don’t forget about exponential notation #

With trailing zeros, exponential notation may be more convenient than grouping zeros. Compare:

const timeoutInMilliseconds = 10e3 ; const tenSecondTimeout = 10 _000;

Numbers aren’t always the best choice to represent numeric(ish) data #

Some data such as phone numbers, credit card numbers and social security numbers, are in some ways numbers, in others not: There may be non-numeric prefixes and separators and leading digits are significant. They should also never be represented in exponential notation.

Therefore – avoid: