TypeScript `charCodeAt` 和 `codePointAt` 的文档已翻转,

w8rqjzmb  于 6个月前  发布在  TypeScript
关注(0)|答案(8)|浏览(64)

Bug报告

charCodeAtcodePointAt 的文档是颠倒的。在 MDN 中有描述,codePointAt 返回 Unicode 码点,而 charCodeAt 返回 UTF16 字符代码,然而在 Typescript 的 JSDoc 字符串中它们是颠倒的。

问题所在

TypeScript/lib/lib.es2015.core.d.ts
第401行到第408行 in 89d05f7
| | /** |
| | * 返回一个小于 1114112(0x110000)的非负整数 Number,表示从字符串元素 pos 在转换为 String 后得到的字符串中起始的 UTF-16 编码码点的代码点值。 |
| | * 如果该位置没有元素,则结果为 undefined。 |
| | * 如果在 pos 不是有效的 UTF-16 代理对的开头,则结果为该位置的代码单元。 |
| | / |
| | codePointAt(pos: number): number|undefined; |
TypeScript/lib/lib.es5.d.ts
第404行到第408行 in 89d05f7
| | /
* |
| | * 返回指定位置的字符的 Unicode 值。 |
| | * @param index 要获取字符的零基索引。如果指定索引处没有字符,则返回 NaN。 |
| | */ |
| | charCodeAt(index: number): number; |

应该如何修复

codePointAt() 方法应返回给定位置的非负整数,即该位置的 Unicode 码点值。请注意,此函数不会给出字符串中的第 n 个代码点,而是从指定的字符串索引开始的代码点。Docs
charCodeAt() 方法应返回表示给定索引处的 UTF-16 代码单元的介于 0 和 65535 之间的整数。Docs

atmip9wb

atmip9wb1#

技术上,当前描述的 codePointAt 是正确的,只是措辞有些令人困惑。它指出返回的值在范围[0,1114111]内,即完整的Unicode范围,并说“从...开始的UTF-16编码的代码点的值”,这也是正确的。代码点确实是用UTF-16编码的(即作为代理对,最多有两个代码单元),了解这一点很重要,这样你就可以正确地选择索引,但函数返回的是完全解码的代码点("值为")。此外:
如果一个有效的UTF-16代理对不从pos开始,结果是位于pos的代码单元。
提到这个例外本身意味着如果那里有一个代理对,你会得到实际的代码点,而不是像charCodeAt那样的第一个代码单元。
charCodeAt 应该绝对改成使用“代码单元”这个词。即使在最好的情况下,“Unicode值”也是模糊不清的。

7eumitmz

7eumitmz2#

codePointAt

"UTF-16编码点代码点的值"这样的措辞似乎令人困惑。我认为MDN更清楚地称之为Unicode代码点
尽管MDN也存在问题,它没有说明当它不是有效代码点时返回undefined。但我认为codePointAt文档不需要提及UTF-16,对吗?

charCodeAt

我认为MDN的charCodeAt措辞更为清晰。

ztmd8pv5

ztmd8pv53#

但是我认为codePointAt文档不需要提及UTF-16,对吗?
在我看来,确实需要提及,因为这个字符串是UTF-16编码的,这改变了pos的意义——在这种情况下,它不仅仅是一个实现细节。不过,我同意目前的说法确实令人困惑。

gijlo24d

gijlo24d4#

MDN表示codePointAt的位置是索引,就像charCodeAt一样。
从指定的字符串索引开始的代码点
UTF16在codePointAt上唯一相关的可能是当它在代理对之间时,正如MDN中提到的那样。
因此,我认为除了这个之外,它还应该被称为:

codePointAt(index: number): number | undefined;
kgsdhlau

kgsdhlau5#

不仅如此,字符串中代理字符的存在还会将其余字符的索引向上推。例如:
https://github.com/spheredev/oozaru/blob/main/web/scripts/fontso.js#L175-L177

92vpleto

92vpleto6#

@fatcerberus 有趣的观点。

循环遍历代码点是否可以用更简洁的方式实现,如下所示:

for (let char of [...text]) {
  let codepoint = char.codePointAt(0);
  // ...
}

(我目前正在制作一个FreeType WASM模块,所以我也确实希望将代码点Map到字形)

rdrgkggo

rdrgkggo7#

我非常确定这将1)分解代理,2)导致更多的垃圾回收压力,创建临时数组,除非引擎针对这种情况进行了特别优化,以避免创建临时数组。
文本处理是棘手的。

bxgwgixi

bxgwgixi8#

这真的很有趣,我会研究这个实现。也许文档可以提到至少对于所有的Unicode点,都存在一个通常带有字形的Unicode字符。但对于字符代码并非如此,因为它们只是位。

相关问题