JavaScript二进制对象全解析:ArrayBuffer、TypedArray与DataView的关系
本文深入解析JavaScript中ArrayBuffer、TypedArray、DataView、Blob等二进制对象的关系与用法。详解如何创建内存块、通过类型化数组或DataView进行读写,以及Blob、File和FileReader在文件处理中的应用,帮助开发者高效处理二进制数据。
前言
随着现代 JavaScript 应用场景日益复杂,数据传输类型也愈发多样,其中二进制数据的传输需求显著增加。为了更高效地处理这些数据,JavaScript 引入了 ArrayBuffer 对象。
然而在实际开发中,开发者会接触到 TypedArray、DataView、Blob、FileReader 等多种对象,容易对其相互关系产生困惑。本文旨在梳理这些对象之间的区别与联系,解答为何需要如此丰富的二进制处理对象。
各种对象的关系
ArrayBuffer
ArrayBuffer 是 JavaScript 中处理二进制数据的基础对象,它代表一段连续的内存空间,以字节(byte)为单位进行计量。
const buffer = new ArrayBuffer(32);
通过上述方式,我们可以创建一块大小为 32 字节的内存区域,并可以通过 buffer.byteLength 属性来查看其长度。
ArrayBuffer 对象本身支持的操作有限,且内容不可直接修改。若需编辑其中的数据,必须借助 TypedArray 或
DataView 对象。
TypedArray
TypedArray(类型化数组)本身并不存储数据,而是专门用于查看 ArrayBuffer 中的数据,因此被称为视图。TypedArray 并非单一的构造函数名,而是一组构造函数的统称。
- Int8Array:1 字节,8 位有符号整数
- Uint8Array:1 字节,8 位无符号整数
- Uint8ClampedArray:1 字节,8 位无符号整数(钳制)
- Int16Array:2 字节,16 位有符号整数
- Uint16Array:2 字节,16 位无符号整数
- Int32Array:4 字节,32 位有符号整数
- Uint32Array:4 字节,32 位无符号整数
- Float32Array:4 字节,32 位 IEEE 浮点数
- Float64Array:8 字节,64 位 IEEE 浮点数
- BigInt64Array:8 字节,64 位二进制有符号整数
- BigUint64Array:8 字节,64 位无符号整数
创建 TypedArray 时可以传入长度、另一个 TypedArray、ArrayBuffer 或普通数组,也可以不传入任何参数。
const uint1 = new Uint8Array(8);
const uint2 = new Uint16Array(new Uint8Array(8));
const uint3 = new Uint8Array(new ArrayBuffer(8));
const uint4 = new Uint8Array([1, 2, 3]);
const uint5 = new Uint8Array();
在上述 TypedArray 中,除了创建时直接传入 ArrayBuffer 不会新建内存块外,其他构造函数在 new 过程中底层都会创建新的 ArrayBuffer。可以通过 arr.buffer 属性访问其引用的 ArrayBuffer。
TypedArray 支持普通数组的大多数操作。但由于 ArrayBuffer 描述的是连续内存区间,因此无法删除单个值(只能赋值为 0),也不支持 concat 方法。
Uint8ClampedArray
Uint8ClampedArray 相对特殊,主要区别在于处理数据溢出时的行为不同。
对于其他类型,存入越界数据时仅保留低位部分,丢弃溢出数据;而 Uint8ClampedArray 会将越界数据钳制为 255,将负数钳制为 0。
字符的相互转换
TypedArray 不支持直接传入字符串,因此需要先进行转码处理。
String → Uint8Array
const string = "Hello";
Uint8Array.from(string.split(""), (e) => e.charCodeAt(0));
Uint8Array → String
// 使用TextDecoder对象
const u8 = Uint8Array.of(72, 101, 108, 108, 111);
new TextDecoder().decode(u8);
// 使用fromCharCode转换
const u8 = Uint8Array.of(72, 101, 108, 108, 111);
Array.from(u8, (e) => String.fromCharCode(e)).join("");
DataView
上述示例中,除了 uint2 变量,其他均为单一数据类型。若一段内存中存放多种类型数据,称为复合视图。由于 JavaScript 数据类型复杂,仅用 TypedArray 操作较为繁琐,因此引入了 DataView 对象,它提供了更丰富的操作方法。
const buffer = new ArrayBuffer(8);
const dataView = new DataView(buffer);
DataView 提供了 getInt8、getUint8、getInt16、getUint16、getInt32、getUint32、getFloat32、getFloat64 等方法。
这些方法包含两个参数:第一个是字节偏移量,第二个是字节序(非必填)。返回值是对应位置的字节数据。
const d1 = dataView.getUint8(1);
const d2 = dataView.getUint8(1, true);
字节偏移量易于理解,字节序可参考《理解字节序》,主要包含两种:
- 大端字节序(big endian):高位字节在前,低位字节在后,符合人类读写习惯。
- 小端字节序(little endian):低位字节在前,高位字节在后,例如以 0x1122 形式储存。
默认情况下使用大端字节序,若需使用小端字节序,需传入 true 作为第二个参数。
至此,我们掌握了基础的二进制读写方案。但在实际应用场景中,数据往往更加复杂,因此衍生出了 Blob、FileReader 等专门针对特定场景的对象。
Blob
Blob 是 Binary Large Object(二进制大型对象)的缩写。
与 ArrayBuffer 的区别在于,ArrayBuffer 仅包含纯二进制数据,而 Blob 包含 MIME 类型信息。此外,Blob 可以方便地从 String、ArrayBuffer、TypedArray、DataView 或另一个 Blob 生成。
const blob1 = new Blob(["hello"], { type: "text/plain" });
const blob2 = new Blob([new Uint8Array([72, 101, 108, 108, 111]), " ", "world"], { type: "text/plain" });
属性:
- size:读取对象的字节大小。
- type:读取或写入的 MIME 类型。
方法:
- slice:提取 Blob 的片段。
URL
在开发中,若获取到图片二进制数据并转换为 base64 写入 src,当数据量巨大或为视频时,可能超出允许长度。此时可使用 URL.createObjectURL 方便地创建资源的 URL。
const url = URL.createObjectURL(blob1);
该方法会生成类似 blob:https://example.com/a6728d20-2e78-4497-9d6c-0ed61b93f11e 的资源 URL,可直接写入 src 属性中使用。
在不再使用时,应调用 URL.revokeObjectURL(url) 销毁引用,以释放内存占用。
数据读取
若要查看 Blob 中的数据,主要有两种方式。
第一种是使用 Response 对象,可直接读取字符串数据或 ArrayBuffer 数据。
const responseText = await new Response(blob2).text();
const responseBuf = await new Response(blob2).arrayBuffer();
第二种是使用 FileReader 对象。
const reader = new FileReader();
reader.onload = function (e) {
console.log(reader.result);
};
reader.readAsText(blob2);
File
File 对象继承自 Blob,并增加了与文件相关的属性信息。
- name:文件名。
- lastModified:最后修改时间的时间戳。
- lastModifiedDate:最后修改时间的 Date 对象。
- webkitRelativePath:文件的路径。在使用 input 选择目录时设置此属性,属于非标准特性。
FileList
FileList 对象是 File 对象的集合,通常出现在以下场景:
- <input type="file"> 控件,其 files 属性是一个 FileList 对象。
- 拖拽事件中产生的 DataTransfer 对象,其 files 属性也是一个 FileList。
属性:
- length:获取当前 FileList 包含的 File 数量。
方法:
- item(index):获取指定索引位置的 File 数据,通常直接使用 FileList[index] 替代。
FileReader
FileReader 在 Blob 章节中已提及,它专门用于读取 Blob 对象,当然也包括扩展的 File 对象。
属性:
- result:文件的内容。
- readyState:状态。0 表示未加载;1 表示正在加载;2 表示加载完成。
- error:加载数据时的错误信息。
事件:
- onload:加载成功后触发。
- onerror:加载错误时触发。
- onabort:加载中断时触发。
- onloadend:加载结束后触发。
- onloadstart:加载开始时触发。
- onprogress:加载中触发。
方法:
- readAsText(blob, "utf-8"):以文本形式返回数据,第二个参数可设置文本编码。
- readAsDataURL(blob):以 Data URL 的形式返回数据。
- readAsArrayBuffer(blob):以 ArrayBuffer 形式返回数据。
- abort:中止操作。
如上面的示例,展示了以文本形式返回数据的用法:
const reader = new FileReader();
reader.onload = function (e) {
console.log(reader.result);
};
reader.readAsText(blob2);
相关资料
- MDN 相关的关键字
- 现代 JavaScript 教程 第三部分 二进制数据,文件
- 阮一峰 JavaScript 教程 浏览器模型相关章节
总结
到此这篇关于 JavaScript 中各种二进制对象关系的文章就介绍到这了,更多相关 JS 二进制对象关系内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!
什么时候该用JS构造器:与工厂模式、字面量的选择对比
2026-11-05 16:18:22
推荐几款轻量级JS照片墙开源库及对比
2026-11-05 15:56:19
JavaScript递归写法有哪些常见陷阱及避免方法
2026-11-05 14:53:38
JS数组浅拷贝与深拷贝怎么选?场景与方法总结
2026-11-05 14:41:02
p5.js 中 setup() 和 draw() 函数的执行机制详解
2026-11-05 12:32:38
