奇怪的知识点

为什么sort((a,b)=>a-b)就是升序?

这是js中基本语法,但我想了解它背后这么定义的原因。网上的很多解释都是a-b<0👉🏻所以a<b👉🏻所以是升序。这对于我来说非常牵强。我想弄懂的是为什么a-b就表示升序

通过查找资料,我发现这不是a-b在数学上小于0的问题,而是JavaScript引擎如何解释比较函数返回值的约定

当你在 sort() 中传入一个比较函数时:

javascript
array.sort(compareFunction)

引擎遵循的规则:

  • 返回负数:a 应该排在 b 前面(a < b 的含义)
  • 返回0:a 和 b 相等,相对位置不变
  • 返回正数:a 应该排在 b 后面(a > b 的含义)

这不是数学上的“小于0”,而是引擎定义的语义约定。

关键理解:不是“a-b 小于0所以 a<b”,而是引擎看到负值,就按照约定把 a 放在 b 前面

除此之外,这种设计源于其他编程语言(如C的qsort)的比较函数传统

// C语言的qsort比较函数
int compare(const void* a, const void* b) {
  return (*(int*)a - *(int*)b);
  // 同样:负数表示a<b,正数表示a>b,0表示相等
}

Unicode & ASCII

在做有效的字母异位词open in new window时,进阶问题是“如果输入字符串包含 unicode 字符怎么办?”我之前常看到这个,但因为开发场景不常用都忽视了,今天我要弄懂它。

这道算法题其实有很多解法,但归类在哈希表解法中。给出的理由是:对于字母异位词问题,使用哈希表(Map)的通用解法可以很好地处理Unicode字符,因为Map的键可以是任意字符(包括Unicode字符)。而使用数组计数的方法只适用于字符范围有限的情况(如只有小写字母)。

Unicode出现的目的:

  • 解决ASCII只能表示英文字符的局限性,使得计算机可以处理多语言文本。
  • 统一之前各种互不兼容的字符编码(如中文的GB2312、GBK,日文的Shift-JIS等),避免乱码问题。
方面ASCIIUnicode
出现时间1963年1991年
设计目标标准化英语字符0x0-0x10FFFF (21位)
编码范围0-127(7位)统一全球所有字符
存储效率固定1字节可变长度(1-4字节)
使用场景纯英文环境国际化多语言

作为前端开发,需要知道

  • 永远使用UTF-8:
  • 注意字符计数:JavaScript的length属性可能不准确
  • 正确处理输入:使用normalize()规范化用户输入
  • 设计字体栈:为不同内容提供合适的字体回退
  • 测试国际化:在不同语言、不同平台上测试你的应用

"1"<"2"为什么也可以比?

起因是我在做字符串解码open in new window这道题时,发现字符串也可以比较大小,平时工作中并不会这样写。我查了一下,这其实是JS中的字符串比较原理

字符串比较是按照字典序(lexicographical order)进行比较的,也就是按照字符的Unicode编码逐个比较,而不是数值大小比较。

console.log("1" < "2"); // true
console.log("a" < "b"); // true
console.log("A" < "a"); // true(大写字母编码小于小写字母)

需要注意的陷阱:

// 这些结果可能违反直觉
console.log("10" < "2");   // true(字典序比较)
console.log("11" < "2");   // true
console.log("100" < "2");  // true

// 数字和字符串混合比较
console.log(10 < "2");     // false("2"被转换为数字2)
console.log("10" < 2);     // false("10"被转换为数字10)

// 这是因为:当数字和字符串比较时,字符串会被转换为数字
// 但当两个字符串比较时,是按字典序比较

(注意上面提到算法题,不是按照大小比,而是按照编码表去比而已。)