前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
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 热点
旧版
首页程序员面试题库ArrayBuffer transfer 与 slice 区别
JavaScript数据处理

ArrayBuffer 的 transfer 和 slice 有什么区别,处理大数据时该用哪个?

slice() 是复制:新建一个 ArrayBuffer,把指定范围的字节拷过去,原来的照常能用。transfer() 是搬家:数据交给新的 ArrayBuffer,原来的变成「已分离」状态,长度变成 0,不能再读写。选哪个先看原数据之后还要不要用。

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

复制还是移交

  1. slice()新分配内存并拷贝,耗时和内存都随数据量增长
  2. transfer()新缓冲区接管数据,原缓冲区的 detached 变成 true
  3. 旧视图基于原缓冲区的 Uint8Array 等视图长度变成 0

transfer() 允许引擎直接复用原来的内存,不做逐字节复制,所以处理大块数据时比 slice() 省内存。但它的价值首先是明确所有权,而不是一个性能开关。

核心回答

先记住这个答案

slice(start, end) 会新分配一块内存,把原缓冲区里指定范围的字节复制过去。两个缓冲区完全独立,改一个不影响另一个,代价是多占一份内存、复制要花时间。transfer() 不复制,它创建一个新的 ArrayBuffer 接管原来的数据,原缓冲区变成「已分离」状态,byteLength 变成 0,基于它创建的视图也全部失效。所以数据要分给多个地方用、原数据还要保留时用 slice();数据处理完交给下一步、原来的不再需要时用 transfer()。

  • slice() 复制字节,两份数据互不影响
  • transfer() 移交内存,原缓冲区长度变 0
  • 转移后基于原缓冲区的旧视图全部失效
  • transfer(n) 能改长度,变长补 0,变短截断

同样三个字节,复制和移交

对两个内容相同的缓冲区分别调用 slice() 和 transfer(),看原缓冲区的状态。

复制后互不影响,移交后原来的空了JavaScript
const copiedSource = Uint8Array.from([1, 2, 3]).buffer
const copied = copiedSource.slice(0)
new Uint8Array(copied)[0] = 9                 // 只改副本
console.log(new Uint8Array(copiedSource)[0], new Uint8Array(copied)[0])

const movedSource = Uint8Array.from([4, 5, 6]).buffer
const moved = movedSource.transfer()          // 数据移交给 moved
console.log(movedSource.byteLength, moved.byteLength)
console.log(movedSource.detached)
console.log(new Uint8Array(moved).join(','))
查看输出与解释
1 9
0 3
true
4,5,6

第一行说明 slice() 出来的副本是独立的,改了副本,原缓冲区的第一个字节还是 1。后面三行是 transfer():原缓冲区长度变成 0,detached 为 true,三个字节都到了 moved 里。 可以把 slice() 想成复印一份文件,原件还在你手里;transfer() 是把原件直接交给别人,你手里只剩一个空文件夹。

转移之后旧视图会怎样

ArrayBuffer 本身不能直接读写,要通过 Uint8Array、DataView 这些视图访问。转移之后,所有基于原缓冲区创建的视图都会失效:length 变成 0,按索引读到 undefined,调用 fill 这类方法会抛 TypeError。

改变长度
transfer() 可以传一个新长度。比原来长,多出来的部分补 0;比原来短,后面的字节被截掉。不管哪种,原缓冲区都会被分离。这在「先分配一块大内存,处理完只保留有用部分」的场景里很方便,比如 buffer.transfer(usedLength)。 所以代码里转移之后,旧变量应该当作已经作废,只把新缓冲区往下传。常见的写法是直接覆盖:buffer = buffer.transfer()。
回答前,多想一步

容易答错的地方

转移后继续用旧的类型化数组
旧视图不会报错提醒你,读出来只是 undefined,很容易被当成数据丢了。转移后要基于新缓冲区重新创建视图。
把 ArrayBuffer.slice 当成共享视图
ArrayBuffer 的 slice() 一定会复制。只想看同一块内存的某一段、不想复制,应该创建带偏移的视图:new Uint8Array(buffer, offset, length)。类型化数组的 subarray() 也是共享内存的,而它的 slice() 会复制。
试着用自己的话回答

面试官还会怎么问?

不支持 transfer() 的环境怎么转移?

transfer() 是 ES2024 加入的,老环境可以用 structuredClone(buffer, { transfer: [buffer] }),效果一样,原缓冲区也会被分离。不能用 slice() 冒充,因为 slice() 之后原缓冲区还能用,行为不一样。

怎样判断一个 ArrayBuffer 已经被分离了?

新环境直接读 buffer.detached。只看 byteLength === 0 不可靠,因为本来就可以创建长度为 0 的缓冲区。

把大文件的数据交给 Worker,应该复制还是转移?

主线程之后不再需要这份数据,就转移:worker.postMessage(buffer, [buffer]),省掉一次复制。两边都要保留数据才复制。只有多个线程需要同时读写同一块内存时,才考虑 SharedArrayBuffer。

从一道题,走向一组知识

把知识连起来

数据处理

怎么把 Blob 转成 ArrayBuffer,有哪些 API 可以用?

要处理的 ArrayBuffer 往往来自 blob.arrayBuffer(),那篇讲读取的几种写法。

数据处理

Blob、File、ArrayBuffer 和 TypedArray 之间是什么关系?

Blob.slice 不一定真的复制字节,而 ArrayBuffer.slice 一定复制,那篇讲清几种二进制类型的关系。

参考资料

  • JavaScript:数据处理参考资料
  • MDN:ArrayBuffer.prototype.slice()

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

本题目录
  1. 先记住这个答案
  2. 同样三个字节,复制和移交
  3. 转移之后旧视图会怎样
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

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

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