ArrayBuffer 是一个字节数组buffer,表示的一块固定大小的内存区域。 这是一个偏低层的对象,所以在性能上表现是比较出色的。
类数组性
简单点看,ArrayBuffer 就是一个数组,里面的元素都是一个字节。 但是没有提供数组完整的 api ,仅支持了部分 api
ArrayBuffer:new ArrayBuffer(10)构造函数创建一个固定大小buffer. 只能通过 api 调整buffer大小resize: 调整 buffer 大小slice: 分割 buffer
TypedArray & DataView
ArrayBuffer 是一个底层对象,不能直接操作其内容。需要借助一个上层对象来操作。
- TypedArray : 是一组对象的统称,每个对象的数据都是指定的数据类型,不存在
TypedArray对象Int8Array: 8位有符号数据 -128 到 127Uint8Array: 8位无符号数据 0 到 255Int16Array: -32768 到 32767Uint16Array: 0 到 65535- 32位 64位
- DataView : 是一个提供对
ArrayBuffer读写的对象。 可以通过DataView的 api 读取,写入 指定位置, 指定类型数据getInt8()&setInt8()读取,写入 一个有符号的8位数据getUint8()&setUint8()读取,写入 一个无符号的8位数据setInt16,setUint16,setInt32,setUint32操作 18 位 , 32 位
const buffer = new ArrayBuffer(3);
const view = new DataView(buffer);
view.setInt8(0, 1); // 在索引0,写入1 00000001
view.setInt8(1, 128); // 在索引1,写入128 10000000
// ( 这里有个陷阱, view.setInt8(1, 128) 实际上写入的 view.setInt8(1, -128) ,你知道为什么吗?)
view.getInt16(0); // 从索引0 ,取16位 00000001 10000000 返回 384
view.getInt16(1); // 从索引1 ,取16位 10000000 00000000 , 最高是1,负数,需要去反 01111111 11111111 + 1 = 10000000 00000000 是 32768 ,返回 - 32768
view.getUint16(1); // 从索引1 ,取16位 10000000 00000000 ,返回 32768
view.getInt8(1); // 返回 -128
Transferable 对象
可转移对象(Transferable Object):就是对象的资源可以一个上下文转移到另一个上下文。 它不是复制,而是直接将对象的资源所有权转移到另一个对象。
worker.postMessage() 在传送 ArrayBuffer 时属于 0 拷贝,速度非常快。 因此在向 worker 传输大量数据时,使用 ArrayBuffer 会是的性能有较大提升。
其他 可转移对象 : ArrayBuffer,MessagePort,ReadableStream,WritableStream 等。
ArrayBuffer在work中性能测试
//index.js
let arr1 = Array.from({ length: 10000000 }, () => '我'); // 约 30M 数据
let u8a = new TextEncoder().encode(arr1.join(''));
const work = new Worker('index2.js');
console.time('work');
work.postMessage(arr1);
// work.postMessage(u8a, [u8a.buffer]);
work.onmessage = function (event) {
console.timeEnd('work');
};
// index2.js
onmessage = function (event) {
self.postMessage(event.data);
// self.postMessage(event.data, [event.data.buffer]);
};
postMessage(arr1): 直接传输数组,约 1400mspostMessage(u8a, [u8a.buffer]): 传输 ArrayBuffer , 约 30ms 。 提升40多倍
使用场景
- 作为底层存储对象 :
TypedArray&DataView - 跨线程传输:
postMessage - Blob 对象转换 :
Blob.arrayBuffer() - FileReader :
FileReader.readAsArrayBuffer(),其result属性是arrayBuffer - Fetch :
Response.arrayBuffer(), 通过 fetch api 获取数据,可以将结果转成arrayBuffer