Uint8Array 是高效字节容器,高性能混淆需卸载至 Web Worker 并通过 ArrayBuffer 零拷贝传递;主线程 transfer buffer 后自动 detached,Worker 用 new Uint8Array(e.data) 创建视图;混淆循环应无内存分配,密钥预加载对齐,全程操作原始字节。

Uint8Array 本身不执行混淆,它只是高效承载字节的“容器”;真正实现高性能混淆的关键,在于把计算密集型逻辑卸载到 Web Worker,并通过 ArrayBuffer 零拷贝传递原始数据——避免主线程阻塞和内存复制开销。
用 ArrayBuffer + transferable 实现零拷贝传参
主线程不能直接把 Uint8Array 实例传给 Worker,否则会深拷贝整个数据。必须提取底层 ArrayBuffer 并显式转移所有权:
- 从 fetch、FileReader 或 WebSocket 二进制接收得到 ArrayBuffer 后,立即用
new Uint8Array(buffer)创建视图 - 调用
worker.postMessage(u8arr.buffer, [u8arr.buffer])—— 第二个参数是 transfer list,必须传.buffer,不能传u8arr - Worker 收到后,可安全创建新视图:
const input = new Uint8Array(e.data),此时主线程的 u8arr 自动 detached,不可再访问
在 Worker 中设计无分配的混淆循环
混淆算法(如 XOR 循环密钥、字节移位、查表置换)应全程操作原始字节,避免创建中间数组或字符串:
- 密钥预加载为
Uint8Array,长度对齐数据块(如 16 字节 AES 密钥),避免运行时重复 slice - 使用
for (let i = 0; i 直接原地修改 <code>u8arr[i],不 push、不 concat、不 join - 若需多轮混淆(如 10 轮异或+旋转),复用同一块内存,仅更新索引与临时变量
- 禁用
Uint8Array.from()、Array.prototype.map()等生成新数组的方法
主线程接收结果并还原可用视图
Worker 完成混淆后,把 ArrayBuffer 发回主线程。由于所有权已转移回来,可立即重建视图:
- 主线程监听
worker.onmessage,拿到e.data(即 ArrayBuffer) - 执行
const result = new Uint8Array(e.data),无需slice()或copyWithin() - 如需导出为文件,直接
new Blob([result], {type: 'application/octet-stream'}) - 如需上传,可转为
FormData.append('file', new Blob([result])),Blob 构造也支持 ArrayBuffer 视图
注意边界与异常防护
混淆过程易因越界或 detached buffer 报错,需提前拦截:
- Worker 入口加守卫:
if (!(e.data instanceof ArrayBuffer) || e.data.byteLength === 0) return - 混淆前检查
u8arr.buffer.byteLength === u8arr.length,确保未被 sliced 过(否则.buffer可能指向更大内存块) - 主线程发数据前,用
u8arr.buffer.constructor === ArrayBuffer和!u8arr.buffer.detached双重校验 - 混淆密钥长度不足时,用
new Uint8Array(32).fill(0)预分配并填充,而非动态拼接


















