TextEncoder
TextEncoder是Web平台Encoding API提供的编码接口,用于把JavaScript字符串按UTF-8转换成字节数组,是浏览器内处理二进制文本的基础组件之一。它只负责编码而不负责解码,解码由配套的TextDecoder完成。由于JavaScript字符串内部以UTF-16存储,而网络传输、文件存储和WebAssembly内存普遍使用UTF-8字节流,TextEncoder因此在数据上传、哈希计算和跨语言数据交换中被广泛使用。
定义
TextEncoder是Encoding API中的编码接口,作用是接收以码点流表示的文本输入,输出对应的UTF-8字节流[1]。它在浏览器和Web Worker环境中均可使用,接口本身不包含解码能力[2]。
该接口提供只读属性encoding,其取值恒为utf-8;构造出的实例只能执行UTF-8编码[3]。与之反向的操作为TextDecoder,两者共同构成Encoding API的编解码机制[1]。
原理
JavaScript引擎内部以UTF-16组织字符串,每个码元占2个字节;TextEncoder的工作是把这些码元重新映射为UTF-8字节序列并装入Uint8Array[4]。UTF-8采用变长编码,ASCII字符占1个字节,U+0080至U+07FF区间的字符占2个字节,U+0800至U+FFFF区间的字符(含中日韩文字)占3个字节,辅助平面字符占4个字节[5]。
接口主要提供2个方法。encode()接收字符串并一次性返回新的Uint8Array;encodeInto()则把结果写入调用方提供的目标数组,并返回包含read与written两个字段的对象,前者表示已转换的UTF-16码元数量,后者表示写入目标数组的字节数[6]。当目标缓冲区空间不足时,read可能小于原字符串长度,而写入部分保证构成完整的UTF-8字节序列[6]。
由于UTF-8是变长编码,输出所需空间介于$s.length$字节与$s.length \times 3$字节之间($s$为源字符串,长度以UTF-16码元计)。据此可以估算缓冲区大小:若输出空间短暂存在,直接分配$s.length \times 3$字节可一次完成转换;若追求内存效率,则先分配较小空间,再依据返回的read值对剩余部分重新分配并续写[5]。
flowchart LR
A[JavaScript 字符串<br/>UTF-16 码元序列] --> B[TextEncoder]
B --> C[Uint8Array<br/>UTF-8 字节序列]
C --> D[网络传输 / 文件 / WebAssembly 内存]
D --> E[TextDecoder 或其他解码器]
E --> F[还原为字符串]
发展历程
TextEncoder最早由W3C的Encoding规范定义,早期草案允许在构造时传入编码标签,并支持utf-8、utf-16be、utf-16le等若干类型,传入无效标签会抛出异常[7]。
Firefox在18版中实现的是较早且略有差异的规范版本,Chrome则在38版至53版期间对未知编码类型抛出RangeError[8]。此后规范调整为编码端只支持UTF-8,Firefox 48、Chrome 54和Opera 41相继移除了其他编码类型;构造函数不再接受有效参数,传入的编码标签被忽略,也不再因未知标签抛出异常[9]。
MDN的兼容性数据表明,encoding属性自2020年1月起在所有主流浏览器中可用,encodeInto()则自2021年4月起获得全面支持[3][6]。作为流式扩展,TextEncoderStream自2022年9月起在所有浏览器中得到支持[10]。
应用
在网络传输场景中,表单、文本内容和二进制协议字段常需以字节形式提交,TextEncoder可以把用户输入的字符串转为可发送的UTF-8字节[1]。配合WebAssembly使用时,encodeInto()能把编码结果直接写入Wasm堆的视图,减少一次中间数组复制,因此比encode()更具性能优势[6]。
在需要按字节处理文本的场合,例如计算消息摘要、生成签名、按固定宽度切分数据包,也需先将字符串编码为字节序列;TextEncoder提供的是同步接口,适合在计算流程中直接调用[1]。部分小程序与跨端框架也按其语义实现了同名对象,例如uni-app x在Web、Android、iOS和HarmonyOS上提供兼容实现[11]。
当数据流分块到达时,可使用流式版本TextEncoderStream,把字符串流逐步转换为UTF-8字节流,而不必等待完整文本拼接完成[10]。
局限
TextEncoder只支持UTF-8,无法生成GBK、ISO-8859系列等传统编码的字节序列;这类转换在编码方向上没有对应的原生接口,需要借助第三方实现[9]。编解码操作因此是不对称的:编码端仅有UTF-8,解码端则可通过TextDecoder识别多种传统编码[1]。
encodeInto()不会在输出末尾追加C风格的0x00终止字节,若下游的WebAssembly程序按C字符串处理,需要自行补写终止符;若源字符串本身含U+0000,则无法避免下游看到被逻辑截断的字符串[5]。此外,encodeInto()总是从目标数组起始位置写入,若要写入指定偏移,需要先用subarray()切出子视图[6]。
不同实现的缓冲区管理策略存在差异。部分实现会按单个字符最大字节数乘以字符串长度预先分配底层缓冲区,导致结果对象的buffer长度略大于实际编码长度,需要按写入长度截取才能得到精确字节数[12]。
参见
-
TextDecoder —— 与TextEncoder互为逆操作的解码接口,负责把字节序列还原为字符串。
-
UTF-8 —— TextEncoder唯一支持的字符编码方案。
-
Uint8Array —— TextEncoder的encode()与encodeInto()所使用的字节数组类型。
-
WebAssembly —— 其堆内存视图是encodeInto()的重点优化场景。
-
JavaScript —— TextEncoder所处理的字符串在该语言中以UTF-16表示。
参考资料
- Encoding API [引用日期2026-10-29]
- TextEncoder extension type [引用日期2026-10-29]
- TextEncoder: encoding 属性 [引用日期2026-10-29]
- github.com 上的网页 [引用日期2026-10-29]
- TextEncoder.encodeInto() - 此页面由社区从英文翻译而来 [引用日期2026-10-29]
- TextEncoder: encodeInto() 方法 [引用日期2026-10-29]
- Encoding - Thefatal attribute's getter must return true if [引用日期2026-10-29]
- TextEncoder() [引用日期2026-10-29]
- TextEncoder [引用日期2026-10-29]
- TextEncoderStream [引用日期2026-10-29]
- # TextEncoder [引用日期2026-10-29]
- faqs-arkts-137 [引用日期2026-10-29]