复用 Intl.Collator 实例可大幅提升中文及国际化字符串排序性能,因其将 locale 规则预编译进对象;须明确指定 locale 为 'zh'、启用 numeric: true,并预处理数据(如过滤、半角化),避免在 sort 回调中重复创建实例。

直接创建并复用 Intl.Collator 实例,是提升海量中文或国际化字符串排序性能最有效的方式——它把语言规则“预编译”进对象内部,避免每次比较都重建逻辑、重复解析 locale 和选项。
预编译的核心:复用 collator.compare 而非反复 new
Intl.Collator 构造过程会加载 ICU 排序规则、初始化权重表、绑定 locale 特定行为(如拼音映射、数字感知),这些开销在首次调用时集中发生。若在 sort 回调里写 new Intl.Collator('zh', { numeric: true }).compare,每对元素比较都会触发一次完整初始化,性能断崖式下降。
- ✅ 正确做法:提前创建实例,再把它的
compare方法传给sort - ❌ 错误写法:
arr.sort((a, b) => new Intl.Collator('zh').compare(a, b))—— 每次比较新建对象,内存与 CPU 双重浪费 - ⚠️ 注意:
collator.compare是已绑定上下文的方法,可直接传递,无需箭头函数包装
关键配置决定预编译质量与适用性
预编译效果不仅取决于“是否复用”,更取决于初始化时的参数是否精准匹配业务场景。错误配置会导致规则加载不全或降级为通用排序,等于白做预编译。
- locale 必须明确指定为 'zh'(而非 'zh-CN' 或 'zh-Hans'):规范推荐 'zh' 才能稳定触发拼音排序逻辑;部分 Android WebView 对子标签识别不稳定,'zh' 兼容性最高
-
必须启用
numeric: true:让 '第10名' 正确排在 '第2名' 之后;若省略,ICU 默认按字符串字典序处理数字,预编译出的规则就失去自然序能力 -
慎用
sensitivity: 'base':它让「张三」「ZhangSan」视为等价,适合混合输入场景;但若数据纯中文且需区分大小写语义(如账号名),应省略或设为'variant' -
避免
usage: 'search':它会简化排序权重以加速模糊匹配,牺牲精度,不适用于严谨列表排序
应对真实数据噪声:预处理比现场判断更高效
预编译后的 collator.compare 对 null、undefined、非字符串值返回 NaN,导致 sort 行为不可预测。与其在 compare 中反复做类型检查,不如在排序前一次性清洗——这本身也是“预处理”的一部分,和 collator 预编译协同提效。
- 先过滤非字符串项:
list.filter(item => typeof item === 'string') - 统一半角化(处理全角数字/空格/标点):
item.replace(/[\uFF10-\uFF19\u3000-\u303F]/g, c => String.fromCharCode(c.charCodeAt(0) - 0xFEE0)) - 若含多音字且业务强依赖上下文读音(如“重庆”需按 zhòng qìng 排),则必须在预处理阶段用词典库标注标准拼音,生成 sortKey 字段,再用 collator 对 key 排序
超大规模场景下的进一步优化
当列表超过 10 万项,或需高频重排(如搜索实时响应),仅靠单个 collator 实例还不够。可叠加以下策略:
- 对固定字段(如姓名、城市名)提取并缓存拼音首字母或完整拼音,构建索引列,用原生数组排序 + 二分查找加速
- 多级排序时,避免在 sort 回调中多次调用
collator.compare;改用预计算 sortKey 数组,例如[collator.compare(name), deptCode, timestamp],再按数组字典序排序 - 服务端渲染或 Node.js 环境下,可考虑将 collator 实例挂载到全局或模块缓存中,跨请求复用(注意 locale 配置一致性)

















