
这个问题不是 JaaScript 特有,只是记录一下。
其实就是 String 的长度的问题。String.length 得到的不是字符数
let str = '哈哈'; console.log(str.length) //8 emoji 占了 2 个长度,这个问题在 js 、java 、go 上有,其他语言还没有测试。
同样的,一些内置函数也受到了这个问题的影响。
let str = '哈哈'; console.log(str.substring(0, 2)); //哈哈 console.log(str.substring(0, 3)); //哈哈 //意料之外的结果 console.log(str.substring(0, 4)); //哈哈 还有 String.charAt()等等
对于 js 解决办法就是把字符串转换成数组
let str = '哈哈'; console.log([...str].length) //5 日常开发中可能大家都依赖 String.length ,但是在某些情况下可能会出 BUG ,比如要遍历字符串的时候,当然如果你确保输入的字符串不会有那些特殊字符那就没问题了。
记录一下我遇到的 bug ,还有处理方法。总的来说就是变成数组
let bug = '哈哈'; console.log(bug.length) //8 console.log([...bug].length) //5 console.log(bug.split("").reverse().join("")) //哈哈 console.log([...bug].reverse().join("")) //哈哈 console.log(bug.substring(0, 3)); //哈哈 console.log([...bug].slice(0, 3).join("")); //哈哈 1 zagfai 2022-05-12 14:23:12 +08:00 字符长度与字节长度是两回事 |
2 DiamondYuan 2022-05-12 14:32:18 +08:00 你的处理方法还是会有 bug console.log([...""].reverse().join("")); |
3 DiamondYuan 2022-05-12 14:33:02 +08:00 |
4 oldshensheep OP @DiamondYuan 看来还是不行……有点坑人。 这个字符我按删除键,变成了另外一个字符…… |
5 pocarisweat 2022-05-12 14:42:59 +08:00 你可以试试更复杂的情况,比如彩虹旗,这个 emoji 实际上是 2 个 emoji (彩虹+白旗)和中间的连接符拼起来的,在 UTF-16 的情况下长度应该是 6 (比如 Javascript )。大概只有 Swift 会把它当作一个字符: 1> "".count $R0: Int = 1 |
6 pocarisweat 2022-05-12 14:44:34 +08:00 @oldshensheep 如果你用的是 Firefox ,那按删除键变成另一个字符是 bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1728746 |
7 oldshensheep OP @pocarisweat 确实是用 Firefox 。不过 Chrome 的地址栏也有这个问题,要按 3 下才能删除( Firefox 是 2 下),网页中的输入框没问题( Firefox 有问题)。 |
8 rabbbit 2022-05-12 14:51:31 +08:00 I have a , I have a . Uh! |
9 rabbbit 2022-05-12 14:53:07 +08:00 这个字符是 + ZWJ + |
10 ipwx 2022-05-12 14:54:44 +08:00 其实让我比较惊讶的是 console.log(str.length) //8 console.log([...str].length) // 5 别的语言要么都是 8 ,要么都是 5 。不愧是大 JS ,继三位一体不等式以后,又出现了新的不一致性。 |
11 hsfzxjy 2022-05-12 14:55:53 +08:00 说到底还是“字符”的定义产生的混淆。你是想要 code point 还是 grapheme https://stackoverflow.com/questions/27331819/whats-the-difference-between-a-character-a-code-point-a-glyph-and-a-grapheme |
12 ipwx 2022-05-12 14:56:31 +08:00 In [1]: S = '哈哈' In [2]: S[::-1] Out[2]: '哈哈' In [3]: len(S) Out[3]: 5 |
14 billlee 2022-05-12 15:22:23 +08:00 ucs-2 的历史遗留问题,java 也有,python 没有 |
15 xtreme1 2022-05-12 15:29:44 +08:00 大部分的 string 问题都是允许按下标访问 如果把 string 和 char array 彻底分开就没这些问题,string 只开放迭代器 |