ArrayBuffer
ArrayBuffer对象用来表示通用的“原始二进制数据缓冲区”。
- 它是一个字节数组,通常在其他语言中称为“byte array”。ArrayBuffer 是一个可转移对象。
- 你不能直接操作 ArrayBuffer 中的内容;而是要通过
类型化数组对象(TypedArray)
或DataView 对象
来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。 - ArrayBuffer() 构造函数创建一个以字节为单位的给定长度的新 ArrayBuffer。你也可以从现有的数据(例如,从 Base64 字符串或者从本地文件)获取数组缓冲区。
ArrayBuffer 大小调整
- ArrayBuffer 对象可以通过在调用 ArrayBuffer() 构造函数时包含 maxByteLength 选项来使其大小可变。
- 通过访问其 resizable 和 maxByteLength 属性来查询 ArrayBuffer 的大小是否可变以及其最大值。
- 可以通过调用 resize() 为可变大小的 ArrayBuffer 分配一个新的大小。新的字节会被初始化为 0。
这些特性使得调整 ArrayBuffer 的大小更加高效——否则,你必须使用新的大小创建一个缓冲副本。这也使得 JavaScript 在这方面与 WebAssembly 相当。
ArrayBuffer 传输
- ArrayBuffer 对象可以在不同的执行上下文之间传输,就像 Web Worker 或 Service Worker 那样,使用结构化克隆算法。
- 通过在 Worker.postMessage() 或 ServiceWorker.postMessage() 的调用中传入 ArrayBuffer 对象作为可转移对象来完成。
- 在纯 JavaScript 中,也可以使用 transfer() 或 transferToFixedLength() 方法来转移内存的所有权。
- 当一个 ArrayBuffer 对象被传输时,它原来的副本会被分离(detached),这意味着它不再可用。在任何时候,只有一个 ArrayBuffer 的副本实际拥有底层内存。分离的缓冲区具有以下行为:
- byteLength 变为 0(在缓冲区和关联的类型化数组视图中)。
- 所有实例方法,比如 resize() 和 slice(),会在调用时抛出 TypeError。关联的类型化数组视图的方法也会抛出 TypeError。
- 你可以通过其 detached 属性来检查 ArrayBuffer 是否已分离。
构造函数
javascript
new ArrayBuffer(length)
new ArrayBuffer(length, options)
new ArrayBuffer(length)
new ArrayBuffer(length, options)
参数:
length
:要创建的数组缓冲区的大小(以字节为单位)。options[可选]
:一个对象,该对象可以包含:maxByteLength 可选(数组缓冲区可以调整到的最大大小,以字节为单位)。
返回:一个指定大小的新 ArrayBuffer 对象,其 maxByteLength 属性设置为指定的 maxByteLength(如果指定了该值),其内容被初始化为 0。
异常:
- length 或 maxByteLength 大于 Number.MAX_SAFE_INTEGER(≥ 253)或者为负数。
- length 大于 maxByteLength。
javascript
// 创建一个 8 字节的缓冲区,它可以调整到的最大长度为 16 字节
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
// 使用resize 调整到的最大长度为 16 字节
buffer.resize(12);
// 创建一个 8 字节的缓冲区,它可以调整到的最大长度为 16 字节
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
// 使用resize 调整到的最大长度为 16 字节
buffer.resize(12);
建议
推荐将 maxByteLength 设置为使用场景下最小的大小。它不应超过 1073741824(1GB),以减少内存溢出风险。
静态方法
ArrayBuffer.isView()
- 描述:判断传入值是否是 ArrayBuffer 视图之一,例如类型化数组对象或 DataView。
- 参数:要检查的值。
- 返回:如果给定参数是 ArrayBuffer 视图之一则返回 true;否则返回 false。
javascript
ArrayBuffer.isView(); // false
ArrayBuffer.isView(null); // false
ArrayBuffer.isView(undefined); // false
ArrayBuffer.isView([]); // false
ArrayBuffer.isView({}); // false
const dv = new DataView(new ArrayBuffer(2));
ArrayBuffer.isView(dv) // true
ArrayBuffer.isView(new Uint8Array()); // true
ArrayBuffer.isView(); // false
ArrayBuffer.isView(null); // false
ArrayBuffer.isView(undefined); // false
ArrayBuffer.isView([]); // false
ArrayBuffer.isView({}); // false
const dv = new DataView(new ArrayBuffer(2));
ArrayBuffer.isView(dv) // true
ArrayBuffer.isView(new Uint8Array()); // true
实例属性
ArrayBuffer.prototype.byteLength
- 描述:该属性返回该数组缓冲区的长度(以字节为单位)。
ArrayBuffer.prototype.detached
- 描述:该属性返回一个布尔值,指示该缓冲区是否已经分离(传输)
ArrayBuffer.prototype.maxByteLength
- 描述:该属性返回该数组缓冲区可调整到的最大长度(以字节为单位)。
ArrayBuffer.prototype.resizable
- 描述:该属性返回此数组缓冲区是否可以调整大小。
实例方法
ArrayBuffer.prototype.resize()
- 描述:调整为指定的大小,以字节为单位。
- 将 ArrayBuffer 调整为 newLength 参数指定的大小,前提是该 ArrayBuffer 是可调整大小的并且新的大小小于或等于该 ArrayBuffer 的 maxByteLength。新字节被初始化为 0。
- 注意,你可以使用 resize() 来缩小和增大 ArrayBuffer——即使 newLength 小于 ArrayBuffer 的当前 byteLength。
javascript
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
if (buffer.resizable) {
console.log("缓冲区大小是可调整的!");
buffer.resize(12);
}
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
if (buffer.resizable) {
console.log("缓冲区大小是可调整的!");
buffer.resize(12);
}
ArrayBuffer.prototype.slice()
- 描述:返回一个新的 ArrayBuffer 实例,其包含原 ArrayBuffer 实例中从 begin 开始(包含)到 end 结束(不含)的所有字节的副本。
javascript
slice()
slice(start)
slice(start, end)
slice()
slice(start)
slice(start, end)
- 参数:
start[可选]
:要开始提取的位置索引(从 0 开始),将被转换为整数。- 负数索引将会从缓冲区末尾开始计算——如果 start < 0,那么将会使用 start + buffer.length。
- 如果 start < -buffer.length 或省略了 start,则会使用 0。
- 如果 start >= buffer.length,则不会提取任何内容。
end[可选]
:要结束提取的位置索引(从 0 开始),将被转换为整数。slice() 提取到但不包括 end。- 负数索引将会从缓冲区末尾开始计算——如果 end < 0,那么将会使用 end + buffer.length。
- 如果 end < -buffer.length,则会使用 0。
- 如果 end >= buffer.length 或省略了 end,则会使用 buffer.length,则会导致直到末尾的所有元素都被提取。
- 如果标准化后的 end 位置在 start 位置之前,则不会提取任何内容。
javascript
// 复制一个 ArrayBuffer
const buf1 = new ArrayBuffer(8);
const buf2 = buf1.slice(0);
// 复制一个 ArrayBuffer
const buf1 = new ArrayBuffer(8);
const buf2 = buf1.slice(0);
ArrayBuffer.prototype.transfer()实验
- 描述:创建一个内容与该缓冲区相同的新 ArrayBuffer 实例,然后将当前缓冲区分离。
ArrayBuffer.prototype.transferToFixedLength()实验
- 描述:创建一个不可调整大小的新 ArrayBuffer 对象,该对象与此缓冲区具有相同的字节内容,然后将此缓冲区分离。