JavaScript 中的二进制数据:ArrayBuffer 与 SharedArrayBuffer 全面解析

1. ArrayBuffer

  • 是什么:一段固定长度、连续的二进制内存。

  • 不能直接读写 ,必须通过视图(TypedArray 或 DataView)访问。

  • 常用场景:

    • 文件读写(图片、音视频)
    • 网络传输(WebSocket、Fetch)
    • WebGL / GPU 数据
    • 加密解密数据
  • 示例:

    js 复制代码
    const buf = new ArrayBuffer(4);
    const u8 = new Uint8Array(buf);
    u8[0] = 255;
    console.log(u8[0]); // 255

2. SharedArrayBuffer

  • 是什么:可以被多个线程同时访问的二进制内存。

  • 不会复制,跨线程传递时是零拷贝。

  • 需要 配合 Atomics 保证数据同步。

  • 浏览器限制:需跨源隔离(COOP/COEP)。

  • 常用场景:

    • 多线程数据共享(主线程 + Worker)
    • 实时游戏(物理计算 + 渲染)
    • 音视频解码与播放共享缓冲
    • 科学计算、机器学习
  • 示例:

    js 复制代码
    const sab = new SharedArrayBuffer(4);
    const u32 = new Uint32Array(sab);
    u32[0] = 123;
    // 传给 Worker 后,两个线程可同时访问并修改

3. TypedArray

  • 是什么 :定型数组视图,用固定类型访问 ArrayBuffer / SharedArrayBuffer。

  • 特点:

    • 高性能批量数值运算
    • 必须按类型大小对齐(如 Int32 按 4 字节)
    • 按系统字节序读写
  • 常用类型 :Uint8Array, Int16Array, Float32Array 等

  • 示例:

    js 复制代码
    const arr = new Uint8Array([1, 2, 3]); // 自动分配底层 ArrayBuffer

4. DataView

  • 是什么:灵活的二进制视图,可按任意偏移读写各种类型,并指定字节序。

  • 特点:

    • 不要求按类型大小对齐
    • 可选大端/小端序
    • 适合自定义二进制格式解析
  • 示例:

    js 复制代码
    const buf = new ArrayBuffer(4);
    const dv = new DataView(buf);
    dv.setUint16(0, 65535, true); // 小端序
    console.log(dv.getUint16(0, true)); // 65535

5. 对比表

特性 ArrayBuffer SharedArrayBuffer TypedArray DataView
是否共享内存 ❌ 否 ✅ 是 依赖底层缓冲区 依赖底层缓冲区
跨线程传递 转移(原失效) 保留引用 依赖底层缓冲区 依赖底层缓冲区
类型 无 无 固定类型 任意类型
字节序控制 无 无 按系统字节序 ✅ 可指定
是否对齐 N/A N/A 必须对齐 不需要
常见用途 文件、网络、GPU 数据 多线程并发 数值计算 文件解析
  • ArrayBuffer(蓝色块)

    • 位于中间,是原始二进制内存块,不能直接读写。
    • 需要通过视图(上方两个白色块)来访问。
  • TypedArray(左上白色块)

    • 一类固定类型、定长的数组视图(如 Uint8Array, Float32Array)。
    • 按系统字节序访问,速度快,适合批量数值计算。
    • 依赖底层的 ArrayBuffer 存储数据。
  • DataView(右上白色块)

    • 更通用的视图,可以按任意偏移读取各种类型,并指定大小端字节序。
    • 灵活度高,适合解析自定义二进制格式。
    • 也依赖底层的 ArrayBuffer。
  • SharedArrayBuffer(下方蓝色块)

    • 与 ArrayBuffer 类似,但可以在多个线程之间共享同一块内存(零拷贝)。
    • 需要配合 Atomics 来保证多线程数据安全。
    • 也能被 TypedArray 或 DataView 作为底层缓冲区使用。

📌 解读:

  • ArrayBuffer / SharedArrayBuffer 是内存本体,负责存放原始数据。
  • TypedArray / DataView 是访问工具,决定如何解释和读写这块内存。
  • SharedArrayBuffer 可以理解为"多线程版 ArrayBuffer",功能更强,但需要同步控制。

SharedArrayBuffer 使用限制及注意事项

SharedArrayBuffer 是 JavaScript 中用于在多个线程(如 Web Worker)间共享内存的底层对象,允许高效的并发数据访问。但它的使用受到多方面严格限制,主要出于安全和兼容性考虑:

  1. 跨源隔离要求(COOP + COEP)

    为防止安全漏洞(如 Spectre 侧信道攻击),现代浏览器要求页面必须开启跨源隔离才能启用 SharedArrayBuffer。

    具体来说,服务器必须设置以下 HTTP 响应头:

    • Cross-Origin-Opener-Policy: same-origin
    • Cross-Origin-Embedder-Policy: require-corp
      只有满足这两个条件,浏览器才允许页面访问 SharedArrayBuffer,否则会被禁用。
  2. 浏览器兼容性

    并非所有浏览器或版本都支持 SharedArrayBuffer。尤其是旧版浏览器或某些隐私模式下,可能完全禁用该功能。开发时应先检测是否支持。

  3. 固定大小且不可变

    SharedArrayBuffer 一旦创建,内存大小就固定了,无法动态扩展,使用时需要提前规划好内存大小。

  4. 必须通过视图访问

    SharedArrayBuffer 本身是底层原始内存块,不能直接读写,必须通过 TypedArray(如 Uint8Array)或 DataView 来访问。

  5. 多线程同步与安全

    由于 SharedArrayBuffer 允许多个线程共享内存,必须使用 Atomics 对象提供的原子操作来同步访问,避免竞态条件和数据损坏。

  6. 安全风险与性能考虑

    该技术虽高效,但使用不当容易引入竞态错误和安全隐患,建议仅在确有多线程共享内存需求且理解同步机制时使用。

相关推荐
子兮曰3 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰3 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万3 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝3 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋3 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁3 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95273 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大3 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师3 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学3 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端