JavaScript中的ArrayBuffer是处理二进制数据的基础对象,它代表一段固定长度的原始二进制数据缓冲区,本身无法直接读写,需要配合类型数组或者DataView才能操作其中的数据。类型数组则是用来读写ArrayBuffer中二进制数据的具体视图,不同类型的类型数组对应不同的数据格式和读取规则。
ArrayBuffer基础概念
ArrayBuffer的实例是一段连续的内存空间,长度在创建时确定,之后无法修改。它不直接提供任何操作数据的方法,仅作为底层存储容器存在。创建ArrayBuffer的方式非常简单,只需要传入需要的字节长度即可:
// 创建一个长度为8字节的ArrayBuffer const buffer = new ArrayBuffer(8); console.log(buffer.byteLength); // 输出8,表示缓冲区长度为8字节
类型数组的分类与使用
类型数组是ArrayBuffer的视图,不同视图对应不同的数据类型,常见的类型数组包括以下几种:
- Int8Array:8位有符号整数,每个元素占1字节,取值范围-128到127
- Uint8Array:8位无符号整数,每个元素占1字节,取值范围0到255
- Int16Array:16位有符号整数,每个元素占2字节,取值范围-32768到32767
- Uint16Array:16位无符号整数,每个元素占2字节,取值范围0到65535
- Float32Array:32位浮点数,每个元素占4字节
- Float64Array:64位浮点数,每个元素占8字节
创建类型数组时可以直接关联已有的ArrayBuffer,也可以指定长度自动创建对应的ArrayBuffer:
// 方式1:关联已有的ArrayBuffer const buffer = new ArrayBuffer(16); // 创建Uint8Array视图,从buffer的0字节开始,读取8字节长度 const uint8View = new Uint8Array(buffer, 0, 8); console.log(uint8View.length); // 输出8,视图包含8个元素 // 方式2:直接指定长度,自动创建对应的ArrayBuffer const int16Array = new Int16Array(4); console.log(int16Array.byteLength); // 输出8,4个元素*2字节=8字节 console.log(int16Array.buffer.byteLength); // 输出8,底层ArrayBuffer的长度
ArrayBuffer与类型数组的关系
可以把ArrayBuffer理解为一块空白的硬盘空间,类型数组就是不同的文件读取工具,不同的工具按照不同的规则读取这块空间里的内容。同一个ArrayBuffer可以关联多个不同类型的类型数组,它们操作的是同一段内存空间:
const buffer = new ArrayBuffer(4); // 创建Uint8Array视图 const uint8View = new Uint8Array(buffer); // 创建Uint16Array视图 const uint16View = new Uint16Array(buffer); // 修改Uint8Array的第一个元素 uint8View[0] = 255; console.log(uint16View[0]); // 输出255,因为Uint16Array的第一个元素由前2个字节组成,第一个字节是255,第二个是0
和普通数组的区别
类型数组和普通数组有以下核心差异:
| 对比项 | 普通数组 | 类型数组 |
|---|---|---|
| 存储内容 | 任意JavaScript数据类型 | 固定类型的二进制数值 |
| 长度 | 动态可变 | 创建后固定不变 |
| 内存占用 | 不固定,每个元素单独分配内存 | 连续内存,每个元素占用固定字节 |
| 性能 | 相对较低 | 处理二进制数据时性能更高 |
常见应用场景
文件读取处理
使用FileReader读取文件时,可以获取ArrayBuffer格式的文件内容,再通过类型数组解析具体数据:
// 假设有一个input元素用于选择文件,id为fileInput
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', function(e) {
const file = e.target.files[0];
const reader = new FileReader();
reader.readAsArrayBuffer(file);
reader.onload = function() {
const buffer = reader.result;
// 读取文件的前4个字节,假设是32位无符号整数
const uint32View = new Uint32Array(buffer, 0, 1);
console.log('文件前4字节表示的数值:', uint32View[0]);
};
});
网络二进制数据传输
在使用WebSocket或者Fetch API传输二进制数据时,经常会用到ArrayBuffer和类型数组:
// 使用Fetch获取二进制数据
fetch('https://ipipp.com/data.bin')
.then(response => response.arrayBuffer())
.then(buffer => {
// 将二进制数据解析为Float32数组
const float32Data = new Float32Array(buffer);
console.log('解析得到的浮点数数据:', float32Data);
});
Canvas图像处理
Canvas的ImageData对象的data属性就是一个Uint8ClampedArray类型数组,可以用来直接操作图像的像素数据:
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
// imageData.data是Uint8ClampedArray,每4个元素代表一个像素的RGBA值
const pixelData = imageData.data;
// 将图像所有像素的红色通道设为255
for (let i = 0; i < pixelData.length; i += 4) {
pixelData[i] = 255;
}
ctx.putImageData(imageData, 0, 0);
使用注意事项
操作ArrayBuffer和类型数组时需要注意以下几点:
- 类型数组的索引和长度都是基于元素个数,而byteOffset和byteLength是基于字节的,不要混淆这两个概念
- Uint8ClampedArray和普通Uint8Array的区别是,前者赋值超过范围时会 clamp 到0-255,而不是取模,适合处理图像像素数据
- 如果需要灵活操作不同数据类型的二进制数据,除了类型数组还可以使用DataView,它支持按任意偏移量读取不同类型的数据
注意:ArrayBuffer和类型数组都是ES6引入的特性,在IE10及以下版本不支持,如果需要兼容低版本浏览器需要做对应的 polyfill 处理。
ArrayBuffer类型数组JavaScript二进制数据修改时间:2026-06-19 22:13:02