ES 提案:数字分隔符

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

什么是数字?

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
parseInt('123_456'); // 123

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

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

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

const RE_NON_DIGIT = /[^0-9]/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;

原文地址:https://2ality.com/2018/02/numeric-separators.html

Copyright © 2019 by Wu WenJun