•  阅读 3 分钟

ES 提案:数字分隔符

由 Sam Goto 和 Rick Waldron 提出的 ES 提案 “Numeric Separators” 正处在 stage 3。这篇博客文章讲解它是如何工作的。

什么是数字?

JavaScript 有几种数字

  • 十进制数字:123.45,86,12e-5
  • 二进制整数数字:0b1011
  • 八进制整数数字:0o765
  • 十六进制整数数字:0x2FF

有意思的是,一元减(-)是一个运算符而不是数字文字的一部分(除了十进制数字中的有符号指数)。

分组数字

分组数字使其具有更好的可读性是有悠久的历史的。举例来说:

  • 截至 2016 年底,慕尼黑拥有 1,464,301 名居民。
  • 地球与太阳之间的距离为 149,600,000 公里。

新的提案允许在数字中使用下划线作为分隔符:

const inhabitantsOfMunich = 1_464_301
const distanceEarthSunInKm = 149_600_000

对于其它的进制数,分组显得同样重要:

const fileSystemPermission = 0b111_111_000
const bytes = 0b1111_10101011_11110000_00001101
const words = 0xFAB_F00D

也可以在分数和指数中使用分隔符:

const massOfElectronInKg = 9.109_383_56e-31
const trillionInShortScale = 1e1_2

约束

需要记住的关键的约束是:你只能在两个数字之间使用下划线分隔符。因此,下面的数字是非法的。

3_.141
3._141

1_e12
1e_12

_1464301  /* valid variable name! */
1464301_

0_b111111000
0b_111111000

另外,绝不能连续使用超过一个下划线在同一行中:

123__456; /* two underscores – not allowed */

这些约束的动机是使事情保持简单。

BigInt(任意精度整数)和数字分隔符

BigInt 能够用数字表示大型数。因此,数字分隔符对它们特别有用:

const massOfEarthInKg = 6_000_000_000_000_000_000_000_000n

BigInt 通常用于代表金融技术领域的资金。分隔符也可以在这里提供帮助:

const priceInCents = 123_000_00 // 123千美元

转换带有分隔符的数字

下面的转换函数不支持分隔符:

  • Number()
  • parseInt()
  • parseFloat()

举例来说:

Number('123_456') // NaN
Number.parseInt('123_456') // 123

原因是数字分隔符是针对代码的。其它类型的输入应该以不同的方式处理

一个转换分隔符数字的辅助函数

一种转换分隔符数字的方法是删除非数字字符:

const RE_NON_DIGIT = /\D/gu
function removeNonDigits(str) {
  str = str.replace(RE_NON_DIGIT, '')
  return Number(str)
}

使用这个函数:

removeNonDigits('149,600,000') // 149600000
removeNonDigits('1_407_836') // 1407836

提示 Tips

不要忘记指数表示法

使用尾随零,指数表示法可能比分组零更方便。对比:

const timeoutInMilliseconds = 10e3 /* 10 秒 */
const tenSecondTimeout = 10_000 /* 10 秒 */

数字并不总是表示数字数据的最佳选择

一些数据,如电话号码,信用卡号码和社会安全号码,在一些方面是数字,而在其他方面则不是:可能有非数字前缀和分隔符,前导数字很重要。它们也不应该以指数表示法表示。

因此避免如此:

// 不要这样做:
const phoneNumber = 555_2368
const creditCardNumber = 378_2822_4631_0005
const socialSecurityNumber = 111_11_1111

本文由 吳文俊 翻译,原文地址 ES2021: numeric separators

> cd ..