奇怪的知识点
为什么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
在做有效的字母异位词时,进阶问题是“如果输入字符串包含 unicode 字符怎么办?”我之前常看到这个,但因为开发场景不常用都忽视了,今天我要弄懂它。
这道算法题其实有很多解法,但归类在哈希表解法中。给出的理由是:对于字母异位词问题,使用哈希表(Map)的通用解法可以很好地处理Unicode字符,因为Map的键可以是任意字符(包括Unicode字符)。而使用数组计数的方法只适用于字符范围有限的情况(如只有小写字母)。
Unicode出现的目的:
- 解决ASCII只能表示英文字符的局限性,使得计算机可以处理多语言文本。
- 统一之前各种互不兼容的字符编码(如中文的GB2312、GBK,日文的Shift-JIS等),避免乱码问题。
| 方面 | ASCII | Unicode |
|---|---|---|
| 出现时间 | 1963年 | 1991年 |
| 设计目标 | 标准化英语字符 | 0x0-0x10FFFF (21位) |
| 编码范围 | 0-127(7位) | 统一全球所有字符 |
| 存储效率 | 固定1字节 | 可变长度(1-4字节) |
| 使用场景 | 纯英文环境 | 国际化多语言 |
作为前端开发,需要知道:
- 永远使用UTF-8:
- 注意字符计数:JavaScript的length属性可能不准确
- 正确处理输入:使用normalize()规范化用户输入
- 设计字体栈:为不同内容提供合适的字体回退
- 测试国际化:在不同语言、不同平台上测试你的应用
"1"<"2"为什么也可以比?
起因是我在做字符串解码这道题时,发现字符串也可以比较大小,平时工作中并不会这样写。我查了一下,这其实是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)
// 这是因为:当数字和字符串比较时,字符串会被转换为数字
// 但当两个字符串比较时,是按字典序比较
(注意上面提到算法题,不是按照大小比,而是按照编码表去比而已。)
