JavaScript数组sort()默认将元素转为字符串后按Unicode码点升序排序,而非数值大小;例如[10,2,33,1]变为[1,10,2,33],因比较的是"10"、"2"、"33"、"1"的字符串首字符。

JavaScript 数组的 sort() 方法在不传比较函数时,**不是按数值大小、也不是按原始类型语义排序,而是统一转成字符串后,逐字符比对 Unicode 码点**。这个行为看似反直觉,但逻辑非常一致——它只做一件事:把每个元素调用 String() 转换,再用字符串比较规则排。
为什么数字 [10, 2, 33, 1] 排成 [1, 10, 2, 33]?
因为 sort() 内部实际比较的是这些字符串:
String(10) → "10"String(2) → "2"String(33) → "33"String(1) → "1"
然后按首字符 Unicode 值排序:"1"(U+0031)、"10"(首字符也是"1")、"2"(U+0032)、"33"(U+0033)。当首字符相同时(如 "1" 和 "10"),继续比第二位:"1" 后无字符,"10" 第二位是 "0"(U+0030),而空字符在比较中被视为小于任何字符,所以 "1" 排在 "10" 前面。最终顺序是:["1", "10", "2", "33"],对应原数组值就是 [1, 10, 2, 33]。
原始类型转换规则很明确
所有原始类型都严格按 String(value) 规则转为字符串,再参与比较:
undefined → "undefined"null → "null"-
true → "true",false → "false" -
0 → "0",-0 → "0",NaN → "NaN" -
123n(BigInt)→ "123"(注意:会报错,BigInt 与 Number 混排时需显式处理)
例如:[undefined, 1, null, '2'].sort() 实际比较的是 ["undefined", "1", "null", "2"],Unicode 顺序为 "1" < "2" < "null" < "undefined",结果就是 [1, "2", null, undefined]。
大小写敏感源于 Unicode 编码本身
大写字母 A–Z 的码点是 65–90,小写字母 a–z 是 97–122。所以 "Apple" 的首字符 "A"(65)比 "apple" 的 "a"(97)小,自然排前面:
-
["banana", "Apple", "cherry"].sort()→["Apple", "banana", "cherry"]
这不是 sort() “故意区分大小写”,而是它老老实实执行了字符串字典序(lexicographic order),而字典序本身由 Unicode 定义——大写就在小写前面。
底层不关心类型,只做字符串比较
sort() 的默认行为等价于内部调用了类似这样的逻辑:
a.toString().localeCompare(b.toString())但更轻量——它不走本地化规则(如忽略重音、处理德语 ß),而是最基础的 UTF-16 码点逐位比对。这也解释了为什么混合类型数组能“勉强排出来”:它不报错,也不分类,只是把一切变成字符串硬比。

















