前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
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 处理BOM ignoreBOM选项
JavaScript数据处理

文件开头带 BOM 时,TextDecoder 会怎么处理?ignoreBOM 是什么意思?

TextDecoder 默认会认出开头的 BOM,把它当成编码标记去掉,不放进结果字符串。设置 ignoreBOM: true 的意思是「不要特殊对待 BOM」,于是 BOM 会作为 \uFEFF 字符留在结果开头。名字和效果正好相反,是最容易答错的地方。

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

BOM 是写在文件开头的编码标记

  1. BOM码点 U+FEFF,放在文本开头,提示编码和字节序
  2. 默认行为解码器在流开头认出 BOM,当标记处理,不输出
  3. ignoreBOM: true不认 BOM 这个身份,把它当普通字符留在结果里

只有开头的 U+FEFF 才算 BOM。正文中间出现的同一个字符是零宽不换行空格,不应该被当成 BOM 删掉。

核心回答

先记住这个答案

BOM 是放在文本最开头的一个特殊字符 U+FEFF,用来标记编码。UTF-8 编码下它是三个字节 EF BB BF。TextDecoder 默认会在流的开头检查有没有和当前编码匹配的 BOM,有的话就当作标记跳过,结果字符串里没有它。如果传了 ignoreBOM: true,意思是「忽略 BOM 的特殊含义」,解码器不再把它当标记,于是它作为普通字符 \uFEFF 留在了结果开头。很多人以为 ignoreBOM 是「忽略掉、删掉 BOM」,正好理解反了。

  • UTF-8 的 BOM 是三个字节 EF BB BF
  • 默认会去掉开头的 BOM
  • ignoreBOM: true 反而保留 BOM
  • 分块解码要复用同一个 decoder

默认和 ignoreBOM: true 的对比

在字母 A 前面加上 UTF-8 的 BOM,用两种选项分别解码。

看 BOM 有没有进入结果JavaScript
const bytes = new Uint8Array([0xef, 0xbb, 0xbf, 0x41]) // BOM + 'A'

const normal = new TextDecoder('utf-8').decode(bytes)
const kept = new TextDecoder('utf-8', { ignoreBOM: true }).decode(bytes)

console.log(normal, normal.length) // A 1,BOM 被去掉了
console.log(kept.length) // 2,BOM 还在
console.log(kept.codePointAt(0).toString(16)) // feff

默认解码得到的字符串只有一个字符 A。开了 ignoreBOM 之后长度是 2,第一个字符是 U+FEFF。在控制台里打印 kept,看起来和 A 一模一样,因为 BOM 是不可见字符,这也是它难排查的原因。 「ignore」在这里的意思是「不理会它的签名作用」,不是「把它扔掉」。真正把它扔掉的,恰恰是默认行为。

BOM 在实际项目里怎么坑人

UTF-8 其实不需要 BOM,因为它按单字节读,没有字节序的问题。BOM 原本是为 UTF-16 设计的,用来区分大端和小端。但 Windows 上的一些工具保存 UTF-8 文件时会带上它,最典型的就是 Excel。

带 BOM 的 JSON 解析失败
有时候 JSON.parse 读一个配置文件,报 Unexpected token,打开文件看又完全正常,很可能就是开头有 BOM。fetch 的 res.json() 和 res.text() 内部会去掉 UTF-8 BOM,不会有问题。但用 Node 的 fs.readFileSync(path, 'utf8') 读文件时,BOM 会保留在字符串开头,JSON.parse 碰到 \uFEFF 就报错。这时要么检查 str.charCodeAt(0) === 0xfeff 后去掉第一个字符,要么用 TextDecoder 默认选项解码。
导出 CSV 时反而要加 BOM
反过来,前端导出 CSV 给用户用 Excel 打开时,如果不加 BOM,Excel 会按系统默认编码去读,中文全变乱码。常见做法是在内容前拼一个 '\uFEFF' 再生成 Blob。这就是 BOM 现在最主要的用途:给不支持编码声明的老软件一个提示。
分块解码要复用同一个 decoder
读大文件或流式响应时,数据是一块一块来的,要用 decoder.decode(chunk, { stream: true }) 并且始终用同一个 TextDecoder 实例。它会记住自己是否已经过了流的开头,只在第一块检查 BOM,也能正确处理被切断在两块之间的多字节字符。每块都 new 一个新的 decoder,被切断的中文字符会变成乱码。
回答前,多想一步

容易答错的地方

以为 ignoreBOM: true 会删掉 BOM
正好相反。默认 false 才会跳过 BOM,设成 true 是关闭这层特殊处理,BOM 会留在结果里。需要 BOM 原样保留的场景很少,比如要把文本原封不动写回文件。
对整个字符串全局替换 \uFEFF
BOM 只在开头才有编码标记的含义。正文里出现的 U+FEFF 历史上用作零宽不换行空格,可能是有意放的。要去 BOM,只处理第一个字符,别用 replace(/\uFEFF/g, '') 全删。
试着用自己的话回答

面试官还会怎么问?

UTF-8 文件必须带 BOM 吗?

不需要,而且 Unicode 标准并不推荐 UTF-8 带 BOM。它只是为了兼容某些软件,比如让 Excel 正确识别编码。网页和接口应该用 Content-Type 头里的 charset 声明编码,而不是靠 BOM。

TextDecoder 会根据 BOM 自动切换编码吗?

不会。TextDecoder 在构造时就定死了编码,它只会检查和这个编码匹配的 BOM。比如用 utf-8 解码器去读一个 UTF-16LE 的文件,开头的 FF FE 不会被当成 BOM,结果是乱码。根据 BOM 嗅探编码是 HTML 解析器做的事,不是 TextDecoder。

BOM 会影响字符串比较吗?

会。带 BOM 的 '\uFEFFname' 和 'name' 用 === 比较是 false,长度也差 1。读 CSV 时表头第一列的列名常常因此匹配不上,调试时可以打印 str.charCodeAt(0) 看看是不是 65279。

从一道题,走向一组知识

把知识连起来

数据处理

中文名字用 sort() 排出来乱七八糟,怎么按拼音或语言习惯排序?

字符串开头藏着一个看不见的 \uFEFF,排序和比较结果都会不对,两题都在处理「看起来一样的字符串」。

数据处理

「张三、李四和王五」这种列表文案,为什么不能直接用 join 拼?

都是文本处理里的细节题,一个处理文本进来时的编码标记,一个处理文本出去时的语言格式。

参考资料

  • JavaScript:数据处理参考资料

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

本题目录
  1. 先记住这个答案
  2. 默认和 ignoreBOM: true 的对比
  3. BOM 在实际项目里怎么坑人
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

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

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