解决在 ES9 中使用 RegExp 对象时遇到的错误

在 ES9 中,RegExp 对象的正则表达式中如果使用到了 Unicode 范围会有一些操作上的限制。本文将介绍这些限制,以及如何解决这些限制带来的问题。

问题描述

在 ES9 中,如果 RegExp 对象的正则表达式中使用了 Unicode 范围,例如 \u{xxxx},那么在以下情况下会遇到问题:

  • RegExp 对象的 lastIndex 属性在与 g 标志连用时不起作用;
  • match()、replace()、split() 等方法会被转化成同步方法, 导致在运行时间长或处理大量数据时会阻塞主线程。

下面是一个例子:

const re = /[\u{24}\u{A2}\u{9C}\u{20A0}\u{20A1}\u{20A2}\u{20A3}\u{20A4}\u{20A5}\u{20A6}\u{20A7}\u{20A8}\u{20A9}\u{20AA}\u{20AB}\u{20AC}\u{20AD}\u{20AE}\u{20AF}\u{20B0}\u{20B1}\u{20B2}\u{20B3}\u{20B4}\u{20B5}/gu;
const str = '$ 0123456789\u00A2\u00A3100\u{20A9}200.40';
const match = str.match(re);
console.log(match);

在上面的例子中,使用了 \u{20AA} 来匹配以色列新谢克尔(ILS)的 Unicode 范围。 在运行例子时,会发现输出结果为空。

解决方案

为了解决这些问题,可以使用 regexp-match-indices 和 regexp-unicode-match-indices 这两个库,它们提供了一系列用于替代 RegExp 方法的异步方法。

regexp-match-indices

regexp-match-indices 提供了以下方法:

  • RegExp.prototype.execAsyn(),与 RegExp.prototype.exec() 方法作用相同,返回的是一个 Promise;
  • String.prototype.matchAllAsyn(),与 String.prototype.matchAll() 方法作用相同,返回的是一个 Promise。

使用 regexp-match-indices 库的示例代码:

const matchIndices = require('regexp-match-indices');

(async() => {
  const re = /[\u{24}\u{A2}\u{9C}\u{20A0}\u{20A1}\u{20A2}\u{20A3}\u{20A4}\u{20A5}\u{20A6}\u{20A7}\u{20A8}\u{20A9}\u{20AA}\u{20AB}\u{20AC}\u{20AD}\u{20AE}\u{20AF}\u{20B0}\u{20B1}\u{20B2}\u{20B3}\u{20B4}\u{20B5}/gu;
  const str = '$ 0123456789\u00A2\u00A3100\u{20A9}200.40';
  const result = await matchIndices.execAsync(reg, str);
  console.log(result[0]);
})();

regexp-unicode-match-indices

regexp-unicode-match-indices 库基于 regexp-match-indices,提供了更多的方法,包括:

  • RegExp.prototype.testAsyn(),与 RegExp.prototype.test() 方法作用相同,返回的是一个 Promise;
  • String.prototype.searchAsyn(),与 String.prototype.search() 方法作用相同,返回的是一个 Promise;
  • String.prototype.matchAsyn(),与 String.prototype.match() 方法作用相同,返回的是一个 Promise;
  • String.prototype.replaceAsyn(),与 String.prototype.replace() 方法作用相同,返回的是一个 Promise。

使用 regexp-unicode-match-indices 库的示例代码:

const {
  RegExpUnicodeMatchIndices,
  StringUnicodeMatchIndices
} = require("regexp-unicode-match-indices");

(async () => {
  const re = /[\u{24}\u{A2}\u{9C}\u{20A0}\u{20A1}\u{20A2}\u{20A3}\u{20A4}\u{20A5}\u{20A6}\u{20A7}\u{20A8}\u{20A9}\u{20AA}\u{20AB}\u{20AC}\u{20AD}\u{20AE}\u{20AF}\u{20B0}\u{20B1}\u{20B2}\u{20B3}\u{20B4}\u{20B5}/gu;
  const str = '$ 0123456789\u00A2\u00A3100\u{20A9}200.40';
  const reumi = new RegExpUnicodeMatchIndices(re);
  const indices = await reumi.execIndicesAsync(str);

  console.log(indices[0][0]);
})();

如果你在项目中使用大量的正则表达式,那么这些库可以帮助你避免在运行时间长或处理大量数据时阻塞主线程。

总结

在 ES9 中,使用带有 Unicode 范围的正则表达式会遇到一些操作上的限制。 使用 regexp-match-indices 和 regexp-unicode-match-indices 这两个库,可以解决正则表达式在遇到这些限制时出现的问题,提高代码的性能和可读性。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/659e5e7eadd4f0e0ff758862


纠错反馈