JS中TextEncoder.encode结果与逐字符取charCode生成数组的差异原因
两种字符串转Uint8Array方案的输出差异原因
你提供的手动转码实现代码如下:
Uint8Array.from( Array.from(value) .map((letter) => letter.charCodeAt(0) ) )
它和TextEncoder.prototype.encode()的输出长度差异主要来自以下几点:
- 核心原因是二者编码规则完全不同
TextEncoder固定采用UTF-8可变长编码规则处理输入:对Unicode码点在U+0000U+007F范围内的ASCII字符用1字节存储,U+0080U+07FF范围内的字符用2字节存储,更高码点的字符会用3~4字节存储,最终输出的Uint8Array长度等于所有字符UTF-8编码的字节数总和。
而手动实现是直接提取每个字符的UTF-16码元,截断低8位后存入Uint8Array,每个字符固定占1字节,长度等于字符串的字符数。当字符串中存在大量非ASCII字符时,TextEncoder的输出长度自然会更长,解密后的加密密钥通常包含大量非ASCII字符,因此这种差异会尤其明显。 - 手动实现本身存在逻辑缺陷
charCodeAt(0)返回的是字符对应的UTF-16码元,对于码点大于U+FFFF的字符(比如大部分emoji、特殊符号),会拆分为两个代理码元,每个代理码元单独截断存入后会丢失原始字符信息,也会进一步放大和TextEncoder输出结果的差异。 - USVString转换带来的是次要影响
JS原始字符串转USVString时,只会把字符串中孤立的代理码元替换为U+FFFD替换字符,这种转换带来的长度变化极小,不是两种方案输出长度差异的核心原因。
内容的提问来源于stack exchange,提问作者David Min
相关产品推荐
相关产品推荐

