【js篇】Unicode、UTF-8、UTF-16、UTF-32 的区别详解

136 阅读5分钟

在计算机中,字符的表示和存储是一个基础而重要的问题。为了支持全球各种语言的字符,我们需要一个统一的编码系统。Unicode 提供了这样的字符集,而 UTF-8、UTF-16、UTF-32 则是 Unicode 的不同编码实现方式


✅ 一句话总结

Unicode 是字符集,定义了全球字符的唯一编号;UTF-8、UTF-16、UTF-32 是编码方式,用于将 Unicode 字符集中的字符转换为计算机可以存储和传输的二进制形式。它们各有优缺点,适用于不同场景。


✅ 一、Unicode:统一码(字符集)

🔹 什么是 Unicode?

  • Unicode 是一个字符集(Character Set),它为世界上几乎所有语言的每一个字符分配了一个唯一的编号,称为码点(Code Point)
  • 例如:汉字“马”的 Unicode 码点是 U+9A6C
  • Unicode 的目标是替代传统的字符编码(如 ASCII、GBK、ISO-8859-1 等),实现全球统一编码

🔹 Unicode 的编码空间

  • Unicode 的编码空间分为 17 个平面(Planes)
    • 第 0 平面(基本多语言平面 BMP):U+0000 ~ U+FFFF
    • 第 1~16 平面(辅助平面):U+10000 ~ U+10FFFF
  • 每个平面有 65536 个字符,总共可以表示 1,114,112 个字符

✅ 二、UTF-8:变长编码,最常用

🔹 定义:

  • UTF-8 是 Unicode 的一种可变长度编码方式,每个字符可以使用 1~4 个字节 来表示。
  • 完全兼容 ASCII(ASCII 字符只占 1 个字节)。

🔹 编码规则:

Unicode 编码范围UTF-8 编码格式(二进制)
U+0000 - U+007F (0-127)0xxxxxxx
U+0080 - U+07FF (128-2047)110xxxxx 10xxxxxx
U+0800 - U+FFFF (2048-65535)1110xxxx 10xxxxxx 10xxxxxx
U+10000 - U+10FFFF (65536-1114111)11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

🔹 示例:汉字“马”(U+9A6C)

  • Unicode 码点:0x9A6C(十进制:39532)
  • 属于第三范围(3 字节编码)
  • 转换为二进制:1001 1010 0110 1100
  • 填入格式:11101001 10101001 10101100
  • 对应十六进制:E9 A9 AC,即 UTF-8 编码为 0xE9A9AC

🔹 特点:

  • ✅ 空间效率高,尤其适合英文为主的文本;
  • ✅ 向后兼容 ASCII;
  • ✅ 网络传输首选(HTML、JSON、HTTP 等默认使用 UTF-8);
  • ❌ 解析复杂,容错性差(某字节损坏可能影响后续字符);

✅ 三、UTF-16:变长编码,适合中文等语言

🔹 定义:

  • UTF-16 也是一种可变长度编码方式,使用 2 或 4 个字节 表示一个字符。
  • 基本平面字符(U+0000 - U+FFFF)使用 2 个字节
  • 辅助平面字符(U+10000 - U+10FFFF)使用 4 个字节(代理对)

🔹 代理对(Surrogate Pair)

  • 基本平面中有一段保留区域 U+D800 - U+DFFF 不表示任何字符;
  • UTF-16 利用这段空间来表示辅助平面字符:
    • 高位代理(High Surrogate):U+D800 - U+DBFF
    • 低位代理(Low Surrogate):U+DC00 - U+DFFF

🔹 示例:字符“𡠀”(U+21800)

  • 码点:0x21800
  • 减去偏移:0x21800 - 0x10000 = 0x11800
  • 转为 20 位二进制:0001000110 0000000000
  • 高位:0xD800 + 0001000110 = 0xD846
  • 低位:0xDC00 + 0000000000 = 0xDC00
  • UTF-16 编码为:0xD846 0xDC00

🔹 特点:

  • ✅ 对中文等常用字符更节省空间(2 字节 vs UTF-8 的 3 字节);
  • ✅ 支持所有 Unicode 字符;
  • ❌ 编码逻辑复杂(代理对机制);
  • ❌ 不兼容 ASCII;
  • ❌ 无法从任意位置开始解析(需要知道字节顺序);

✅ 四、UTF-32:定长编码,最简单但最占空间

🔹 定义:

  • UTF-32 是 Unicode 的一种固定长度编码方式,每个字符都占用 4 个字节
  • 它直接将 Unicode 码点转换为 32 位整数。

🔹 示例:汉字“马”(U+9A6C)

  • Unicode 码点:0x9A6C
  • UTF-32 编码为:0x00009A6C(32 位二进制)

🔹 特点:

  • ✅ 编码解码简单,无需处理变长;
  • ❌ 存储空间占用大(英文字符也占 4 字节);
  • ❌ 实际应用较少,主要用于内存处理;

✅ 五、总结对比表格

特性UnicodeUTF-8UTF-16UTF-32
类型字符集(定义字符)编码方式编码方式编码方式
编码长度-1~4 字节2 或 4 字节固定 4 字节
是否兼容 ASCII-✅ 是❌ 否❌ 否
空间效率-英文最优中文最优最差
编码复杂度-中等复杂(代理对)最简单
应用场景-网络传输、JSON、HTMLWindows、Java、JavaScript内存操作、内部处理
容错能力-弱(影响后续字符)强(仅影响当前字符)

✅ 六、一句话总结

Unicode 是字符集,UTF-8、UTF-16、UTF-32 是其不同的编码方式。UTF-8 在网络传输中占主导地位,UTF-16 适合处理中文等非英文字符,UTF-32 虽然简单但占用空间大,主要用于内部处理。


💡 进阶建议

  • 网络传输、前端开发首选 UTF-8;
  • Java、JavaScript 内部使用 UTF-16;
  • UTF-32 用于需要快速访问字符的场景(如图形渲染);
  • 处理 Emoji、古文字等辅助平面字符时需注意代理对问题;
  • 使用 BufferTextEncoderTextDecoder 等 API 进行编码转换;