前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库TextDecoder 非法UTF-8 fatal 替换处理
JavaScript数据处理

字节不是合法 UTF-8 时,TextDecoder 会报错还是出乱码?

默认不报错。TextDecoder 会把解不出来的字节替换成 U+FFFD(显示为 �),其余内容照常返回。想让它遇到坏字节就抛 TypeError,构造时传 { fatal: true }。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#数据处理#流处理
先看核心答案读代码示例
理解线索

坏字节怎么处理和 BOM 怎么处理是两个开关

  1. 替换模式默认行为,坏字节变成 �,适合展示用户内容
  2. fatal: true坏字节直接抛 TypeError,适合导入、校验、协议解析
  3. ignoreBOM默认 false 会吃掉开头的 BOM,设为 true 反而把它留在结果里

默认模式下,损坏的文件也能「正常」解码出一个字符串。用它来判断数据是否完整是不行的,要验证完整性必须开 fatal。

核心回答

先记住这个答案

TextDecoder 默认是容错的:遇到不合法的 UTF-8 字节,它把这段字节替换成 U+FFFD 替换字符(就是那个黑色菱形里带问号的 �),然后继续往下解码,不会抛错。构造时传 { fatal: true } 就切换到严格模式,遇到坏字节直接抛 TypeError。另一个选项 ignoreBOM 管的是文本开头的 BOM 标记,和坏字节处理无关,而且它的名字很容易理解反。

  • 默认把坏字节替换成 �,不抛错
  • fatal: true 遇到坏字节抛 TypeError
  • ignoreBOM: true 是保留 BOM,不是删掉 BOM
  • 编码选错时 fatal 只能报错,不能帮你猜对

默认模式和严格模式的区别

先造一段坏数据:0xff 在 UTF-8 里永远不可能出现,把它夹在 A 和 B 中间。

同一段字节,两种解码结果JavaScript
const bytes = new Uint8Array([0x41, 0xff, 0x42]) // A、非法字节、B

console.log(new TextDecoder().decode(bytes)) // 'A�B',坏字节被替换

const strict = new TextDecoder('utf-8', { fatal: true })
try {
  strict.decode(bytes)
} catch (err) {
  console.log(err.name) // 'TypeError'
}

默认模式把 0xff 换成 �,前后的 A 和 B 都保住了。严格模式一个字符都不返回,直接抛错。 选哪种要看场景。展示聊天记录、日志、用户上传的文本预览时,用默认模式,一个坏字节不该让整页内容都显示不出来。导入配置文件、解析协议、校验签名数据时,用 fatal: true,因为静默替换会把损坏藏起来:数据坏了,程序却以为一切正常,等到后面某个字段对不上才发现,很难追到源头。

截断的字符也算坏字节
除了 0xff 这种本来就非法的字节,最常见的是被截断的多字节字符。比如 € 是 E2 82 AC 三个字节,只给前两个 E2 82,默认模式输出一个 �,严格模式抛 TypeError。如果是流式解码传了 stream: true,解码器会先把这两个字节缓存着,等到流结束那次 decode() 还凑不齐,才按上面的规则处理。

ignoreBOM 为什么容易理解反

BOM 是放在文本最开头的几个字节,用来标记编码和字节序。UTF-8 的 BOM 是 EF BB BF,Windows 记事本早年保存 UTF-8 文件时常会带上它。

名字说的是「忽略 BOM 的特殊处理」
默认 ignoreBOM: false 时,解码器认出开头的 BOM 后会把它吃掉,结果里只有正文。设成 true 表示忽略 BOM 的特殊含义,把它当成普通字符 U+FEFF 留在结果里。所以带 BOM 的 EF BB BF 41 默认解出来是 'A',长度 1;ignoreBOM: true 解出来长度是 2,第一个是看不见的 U+FEFF。 这个字符看不见但真实存在。读 CSV 时,第一列的表头会变成 '\uFEFFname',用 row.name 取值拿到 undefined,是很经典的坑。大多数情况保持默认就对了。
回答前,多想一步

容易答错的地方

以为 ignoreBOM: true 是删掉 BOM
正好相反。默认就会删,设成 true 才会保留。
以为 fatal 能识别编码错误
一个 GBK 文件用 UTF-8 去解,fatal: true 大概率会抛错,但它只能告诉你「这不是合法的 UTF-8」,不会告诉你正确的编码是什么。而且有些字节序列恰好在两种编码下都合法,这时不报错,只会得到一串错的文字。编码应该来自 HTTP 的 Content-Type、文件格式约定这类可信来源,而不是靠 fatal 去试。
用默认模式判断数据是否完整
默认模式下损坏的数据也能解码成功,返回的字符串里多几个 �。想确认数据没坏,必须开 fatal,或者自己检查结果里有没有 �。
试着用自己的话回答

面试官还会怎么问?

TextDecoder 能解 UTF-16 吗?

能。构造时传 'utf-16le' 或 'utf-16be',区别是字节序:「你」的码点是 U+4F60,小端存成 60 4F,大端存成 4F 60。两个选项 fatal 和 ignoreBOM 在 UTF-16 下一样生效,UTF-16 的 BOM 是 FF FE(小端)或 FE FF(大端)。除了 UTF-8 和 UTF-16,它还支持 GBK、Big5 等常见编码。

替换字符的个数能反推出坏了几个字节吗?

不能精确反推。解码算法按规则把非法序列分段,每段一个 �。一个孤立的 0xff 是一个 �,一个被截断的三字节字符的前两个字节合起来也只是一个 �。所以 � 的数量和坏字节的数量没有固定比例。

严格模式下怎么只跳过坏的那部分?

fatal 是全有全无的,抛错后拿不到任何结果。想做到「记录错误但保留其余内容」,就用默认模式解码,然后在结果里搜 � 统计位置,自己决定是告警还是拒绝。

从一道题,走向一组知识

把知识连起来

数据处理

TextEncoder 为什么只能输出 UTF-8,能指定成 GBK 吗?

TextEncoder 碰到孤立的代理项也会写出替换字符的三个字节,和解码方向的替换是对应的。

数据处理

Uint8Array 和普通数组有什么区别?

decode() 接收的是 Uint8Array 这类视图,传子视图时只会解码视图覆盖的那段字节。

参考资料

  • JavaScript:数据处理参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 默认模式和严格模式的区别
  3. ignoreBOM 为什么容易理解反
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑