在 ECMAScript 2020 (ES11) 中,正则表达式捕获分组返回 undefined 的问题已经被修复了。这个问题源于之前的规范中强制使用 undefined 来初始化捕获列表中未匹配的分组,导致出现一些意外的结果。这篇文章将介绍这个问题的原因和解决方法,帮助读者更好地理解正则表达式的细节,以及如何编写可靠的 JavaScript 代码。
问题描述
在旧的规范中,当一个正则表达式的捕获分组没有匹配时,这个分组的值会被初始化为 undefined。这个特殊的行为,可以被归结为 ECMAScript 2018 规范中的标准函数 MakeCapturedIndexProperties。
-- -------------------- ---- ------- -------- ------------------------------- ------- ---- ------- ----- ------------ ---- - --- --- ------ - -- ------------- - -- ---- -- ------ - ----------- - ----------------- - ----------- - ---- - ---------------- - --- - -
针对这个问题,我们可以看到在 MakeCapturedIndexProperties() 函数的实现中,当分组序号 i 不在 caps 中时,他将被初始化为 undefined。
这样的行为通常对于简单的正则表达式并不会有问题,但是在复杂的表达式中,有时我们会依赖未匹配的捕获分组去做后续的逻辑操作。以此为例,我们先声明一个正则表达式 regex,使用正则表达式的 replaceAll() 函数方法,将匹配到的字符串替换为它的首字母,并使用未匹配的捕获分组构建新的字符串。
const regex = /(\w)(\w+)/g; const str = 'hello world'; const newStr = str.replaceAll(regex, '$2$1'); console.log(newStr);
在旧的规范中,执行这段代码会输出 'o lledhwor' ,这个执行结果看起来显然不符合我们的预期。
解决方法
为了解决这个问题,在 ECMAScript 2020 (ES11) 中,规范对于 MakeCapturedIndexProperties() 函数做了修订,让未匹配的捕获组在捕获列表中跳过。这意味着,现在只有已经捕获了的分组才会出现在捕获列表中,而没有捕获的分组即使匹配成功也不会出现在捕获列表中。
这个改变,代表着进行正则表达式分组匹配时我们需要注意的细节,我们需要保证一个捕获分组被已经确保被匹配,才可以在应用正则表达式的捕获列表时,使用它的匹配内容。如果没有捕获到该分组,我们需要注意防止在后续的操作中使用对未定义变量重新赋值的行为。可以使用 ?. 运算符避免这种行为。
示例代码
-- -------------------- ---- ------- ----- ----- - ------------- ----- --- - ------ ------- ----- ------ - --------------------- ------- --- --- -- - -- ---- - ------ -- - --- - ------ ------ --- --------------------
以上代码在新的规范中会输出我们期望的 'o llehwor'。在这段代码中,我们使用了一个回调函数来替换相关的字符串。在这个回调函数中,我们使用了 ?. 运算符去保证分组 $2 已经被成功匹配,以防止 undefined 对字符串操作执行非预期操作。
总结
在 ECMAScript 2020 (ES11) 中,解决正则表达式捕获分组返回 undefined 的问题,是对规范的一次修订。对于开发者来说,也需要在相关的代码中增加对于正则表达式的细节判断,避免出现非预期的行为。上述示例代码提供了一个新规范下的解决方案,以供读者参考。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/6475a928968c7c53b02abcee