es2018中的不区分大小写字符串操作

4
我们在JavaScript中的String对象中提供了多个本地方法: 它们都是区分大小写的。
当涉及到不区分大小写的操作时,我们有一些常用的选项,虽然它们都还远远不够理想。

toUpperCase()toLowerCase()

最常用的技巧是使用toUpperCase()toLowerCase()方法。然而,它们并不能正常处理所有语言(德语、土耳其语等),而且把两个字符串都转换为大写或小写的操作会对性能造成影响,尽管通过查看前一对字符的结果就可以知道操作的结果。

正则表达式

第二个选项是使用带有i选项的正则表达式。然而,它也有两个主要缺点:
  • 不明确和混乱的代码(因为它几乎总是与正则表达式一起出现)
  • 由于组合正则表达式字符串并将其编译成实际正则表达式所造成的性能开销
此外,这些解决方案都是在古老的JavaScript VM时代“发明”的。如今,我们可以轻松地应用最新的JavaScript API(例如Intl和其他更新的API)以及像TypeScript和Babel这样的转换器,以及像core-js这样的polyfill库来解决任何应用程序中的问题。
es2018中不区分大小写的String操作的解决方案是什么呢?
我正在寻找一个生产级别(考虑MDN polyfills)的、高效的、i18n友好的代码,它被设计为通用的解决方案。

2
在进行比较之前转换为大写是最好的选择。 - Pointy
2
此外,如果您不想在检查之前将整个字符串转换为小写/大写,可以始终先对字符串进行切片。例如,不要使用'foObAR'.toLowerCase().startsWith('foo'),而是使用'foObAR'.slice(0, 3).toLowerCase().startsWith('foo') - CertainPerformance
1
@giorgiga 在今天之前,我会同意你的看法,但事实证明有一些“不稳定”的Unicode代码点不能以可靠的方式转换为小写。您可以编写一个简单的测试:通过调用String.fromCharCode()遍历16位值,并将.toLowerCase().toUpperCase()与仅.toUpperCase()进行比较,其中几个字符未通过测试! - Pointy
@CertainPerformance,您能详细说明一下“只需使用正则表达式字面量,而不是字符串”的含义吗?如果我们有两个字符串作为变量,如何使用预编译的字面量来实现s1,startsWithCaseInsensitive(s2)呢? - Alexander Abakumov
@CertainPerformance的评论:“您始终可以事先切割字符串”。1.如何定义在startsWithCaseInsensitive() polyfill中进行“切片”的字符数?2. “切片”意味着(a)内存分配和(b)某种内存区域复制的循环(尽管后者可能编译为单个高级CPU指令)。这种优化效益完全取决于字符串的长度,并且可能是通用polyfill的不必要过度复杂化。至少,我从未在MDN polifills中看到过这样的优化目标案例分析。 - Alexander Abakumov
显示剩余2条评论
1个回答

0

这里是一些不区分大小写的 startsWith 实现:

不需要将整个字符串转换为小写,而是仅使用测试字符串的长度:

function startsWith_Insensitive(str, test) { 
    return str.substr(0, test.length).toLowerCase() === test.toLowerCase();
}

我认为逐个转换和测试字符,如果有任何不同就停止,而不是全部转换然后再测试,这样也更有效率,代码如下:

function startsWith_Insensitive(str, test) {
    if (str.length < test.length) return false;
    for (let i = 0; i < test.length; i++) {
        if (str[i].toLowerCase() !== test[i].toLowerCase()) 
            return false    
    } 
    return true    
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接