You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TextDecoder(latin1)与String.fromCharCode输出差异原因探究

TextDecoder('latin1') 与 String.fromCharCode 处理0-255码点结果不同的原因

核心差异来自两个API的设计逻辑和实际实现规则:

1. String.fromCharCode 的行为

String.fromCharCode(...codes) 是直接将输入数值作为UTF-16码元映射为Unicode字符。对于0-255的数值,它会严格对应Unicode U+0000到U+00FF的码点——包括0x80-0x9F(128-159)区间的未定义控制字符(比如U+0080、U+0081这类无显示意义的控制码)。

2. TextDecoder('latin1') 的实际行为

虽然你指定了latin1(即ISO-8859-1)编码,但JavaScript环境中的TextDecoder实现实际上采用了Windows-1252编码规则(这是ISO-8859-1的超集):

  • ISO-8859-1标准中,0x80-0x9F(128-159)的字节属于未定义的控制字符范围;
  • 而Windows-1252把这些空白字节映射到了常用的Unicode符号、标点(比如0x80对应欧元符号€(U+20AC),0x82对应单低引号‚(U+201A),0x93对应左双引号“(U+201C)等)。

差异具体对应

你找到的差异索引[128, 130, 131, ..., 159]刚好覆盖0x80-0x9F区间:

  • 比如索引128(数值128):String.fromCharCode(128)生成U+0080(无显示的控制字符),而TextDecoder('latin1').decode(Uint8Array.of(128))生成U+20AC(€);
  • 索引130(数值130):String.fromCharCode(130)生成U+0082,而TextDecoder生成U+201A(‚)。

验证代码

可以用单个值测试直观对比:

// 测试0x80(数值128)
console.log(String.fromCharCode(128)); // '\x80'(U+0080)
console.log(new TextDecoder('latin1').decode(new Uint8Array([128]))); // '€'(U+20AC)

// 测试0x93(数值147)
console.log(String.fromCharCode(147)); // '\x93'(U+0093)
console.log(new TextDecoder('latin1').decode(new Uint8Array([147]))); // '“'(U+201C)

内容的提问来源于stack exchange,提问作者Brad Script

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 16:32:48