TextEncoder / TextDecoder 不往返

DRa*_*ayX 4 javascript unicode

我肯定遗漏了有关 TextEncoder 和 TextDecoder 行为的一些内容。在我看来,以下代码应该往返,但似乎并非如此:

new TextDecoder().decode(new TextEncoder().encode(String.fromCharCode(55296))).charCodeAt(0);
Run Code Online (Sandbox Code Playgroud)

因为我只是对字符串进行编码和解码,所以 char 代码看起来应该是相同的,但这返回 65533 而不是 55296。我错过了什么?

xdh*_*ore 6

根据一些探索,该TextEncoder.encode()方法似乎采用类型的参数 USVString,其中 USV 代表 Unicode 标量值。根据此页面,USV 不能是高代理或低代理代码点。

另外,根据 MDN:

USVString 是 Unicode 标量值的序列。此定义与 DOMString 或 JavaScript String 类型的不同之处在于,它始终表示适合文本处理的有效序列,而后者可以包含代理代码点。

所以,我的猜测是你的String论点encode()正在转换为 a USVString(隐式或在 内encode())。根据此页面,它看起来像是从 转换StringUSVString,它首先将其转换为 a DOMString,然后遵循此过程,其中包括将所有代理项替换为U+FFFD,这是您看到的代码点,65533“替换字符”

我认为有效的原因String.fromCharCode(55296).charCodeAt(0)是因为它不需要进行这种String -> USVString转换。

至于为什么TextEncoder.encode()这样设计,我不太了解 unicode 细节,无法尝试解释,但我怀疑这是为了简化实现,因为它支持的唯一输出编码似乎是 UTF-8,在Uint8Array. 我猜测需要一个USVString没有代理的参数(而不是String可能带有代理的本机 UTF-16 )会将编码简化为UTF-8,或者可能使某些编码/解码用例更简单?