regex 总览待审核
字符的真面目 · 排序不在码点里

排序:为什么 arr.sort() 把 Z 排在 a 前面

["Z","a"].sort() 得到 ["Z","a"] —— 默认的 sort()UTF-16 码元值逐个比较,而大写字母的码点全在小写之前,带音标的字母又全被甩到 ASCII 之后,"file10" 还会排在 "file9" 前。真正「按某种语言的字典序」排序,由 Unicode Collation Algorithm(UCA)定义,JS 里走 Intl.Collator。和 拼音那页同理:排序规则不写在码点里,是另一份按 locale 调的权重表。

默认 sort() 是码元序,不是字母序

左边是 arr.sort()(按 UTF-16 码元),右边是 arr.sort(new Intl.Collator(locale).compare)位置不同的行会高亮 —— 码元序里大写聚一堆、小写聚一堆、带音标的垫底,根本不是人读的顺序:

arr.sort()按 UTF-16 码元值

    Intl.Collator按语言的字典序

      三层权重:sensitivity 决定「忽略到哪一层」

      UCA 给每个字符算多级权重:primary(基字母,a vs b)、secondary(变音,a vs á)、tertiary(大小写,a vs A)。Intl.Collatorsensitivity 选项就是「比到第几层」 —— 比得越浅,越多字符被当成相等:

      每格:collator.compare(左, 右)< / = / >(= 高亮表示这一层把它们看成相等)

      怎么选:不分大小写、不分音标的搜索sensitivity:'base';区分音标但不分大小写用 'accent';完整排序(默认)用 'variant'。注意 compare(a,b)===0 表示「排序意义上相等」,不等于 === —— 比较前若还担心同字多形,先 normalize

      locale 不同,顺序就不同

      同一组字母,不同语言排出的顺序不一样。瑞典语把 å ä ö 放到 z 之后(字母表末尾),德语把 äa 的变体排在一起,英语则把所有音标都当次级差异:

      a z ä ö å 用各 locale 排序

      numeric:让 file10 排在 file9 之后

      字符串里的数字,默认按字符比('1' < '9',所以 "file10" 排在 "file9" 前)。Intl.Collatornumeric:true 会把连续数字当数值比 —— 这正是文件管理器里「自然排序」的做法:

      默认数字逐字符比

        numeric: true连续数字当数值比

          一句话收束:凡是给人看的排序、或大小写 / 音标无关的查找,都别用裸 sort()< —— 那是码元序。用 Intl.Collator(locale, { sensitivity, numeric }),把「按哪种语言、忽略到哪层、数字怎么比」交给标准。中文排序传 'zh' 即按拼音,和 拼音那页是一回事。