JavaScript字符串的安全长度是多少?

4
考虑到charAt(), charCodeAt(), 和codePointAt(),我发现参数的含义存在差异。在真正思考之前,我认为你总是可以安全地访问length-1处的字符。但是,我了解到charCodeAt()和codePointAt()之间的区别在于,charCodeAt()是16位(字节对),因此除了读取i之外,如果它们是代理对(如UTF-16的方法),还需要i+1。而codePointAt()需要一个引用UTF-8字符位置(从零开始)的参数。所以现在我陷入了一个困境,不确定length计算的是字符数还是字节对数,像UTF-16这样。我相信JavaScript将字符串保存为UTF-16,但是在使用codePointAt()函数处理具有大量4字节字符的字符串时,从length-1处开始会超出字符串的末尾!

字符串可以是任意长度,只要有足够的内存。 - StackSlave
2个回答

3
该字符串的长度是用16位无符号整数值(“元素”)代码单元(它们一起构成一个有效或无效的UTF16代码单元序列)进行计数的,因此其索引也是如此。我们也可以称它们为“字符”。length

无论您是通过属性访问还是通过charAt, chatCodeAtcodePointAt访问它们,length - 1始终是有效的索引。但是,一个代码点可能被编码为跨越两个索引的代理对。没有内置方法来测量这些字符的数量,但默认的字符串迭代器将产生它们,因此您可以使用for … of循环来计数。


请为提问者的问题“安全长度是多少”提出一个解决方案。 - Tatsuyuki Ishi
感谢您的回答。但非常失望的是,JavaScript 在处理代理对中第二个字符的索引时会提供非法返回值,这使得它变得毫无用处。 - Clive
@Clive 你所说的“非法”是什么意思?它只是该索引处的代码单元,与其前面可能有的字节无关。但是没错,JavaScript字符串是不可变的Uint16Array,而不是Unicode字符列表。 - Bergi
@Bergi 我称之为非法,是因为这三个函数的名称中都包含子字符串'char'。从它们的名称来看,它们声称提供“字符”的代码,而不是_16位无符号整数值_的代码。 - Clive
@Bergi。 "irregardless" - 哇,那是布什的话吗?(就像“misunderestimated”)哈哈 - Clive

2

使用[...str].length来统计字符数。

var mb = "";
console.log(mb.length);
console.log([...mb].length); // "real" length (ES6)
console.log(mb.charAt(0)); // The first two byte
console.log(mb.codePointAt(0)); // The first two byte
console.log(mb.codePointAt(1)); // The second two byte
console.log(mb.charCodeAt(0)); // The four bytes combined (ES6)
console.log(mb.charCodeAt(1)); // The second two byte (ES6)


我假设你所说的mb字符集是非基本多语言平面字符。谢谢你的回答和附带的源代码。但是我对JavaScript的length属性感到困惑,它似乎并没有明确表示有多少个字符。我之前不知道有省略号这个概念。 - Clive
我建议使用 Array.from(…) 将可迭代对象转换为数组,展开语法应该只用于字面量的一部分。 - Bergi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接