Skip to content

ArrayBuffer

ArrayBuffer对象用来表示通用的“原始二进制数据缓冲区”

  • 它是一个字节数组,通常在其他语言中称为“byte array”。ArrayBuffer 是一个可转移对象。
  • 你不能直接操作 ArrayBuffer 中的内容;而是要通过类型化数组对象(TypedArray)DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。
  • ArrayBuffer() 构造函数创建一个以字节为单位的给定长度的新 ArrayBuffer。你也可以从现有的数据(例如,从 Base64 字符串或者从本地文件)获取数组缓冲区。

ArrayBuffer 大小调整

  1. ArrayBuffer 对象可以通过在调用 ArrayBuffer() 构造函数时包含 maxByteLength 选项来使其大小可变。
  2. 通过访问其 resizable 和 maxByteLength 属性来查询 ArrayBuffer 的大小是否可变以及其最大值。
  3. 可以通过调用 resize() 为可变大小的 ArrayBuffer 分配一个新的大小。新的字节会被初始化为 0。

这些特性使得调整 ArrayBuffer 的大小更加高效——否则,你必须使用新的大小创建一个缓冲副本。这也使得 JavaScript 在这方面与 WebAssembly 相当。

ArrayBuffer 传输

  1. ArrayBuffer 对象可以在不同的执行上下文之间传输,就像 Web Worker 或 Service Worker 那样,使用结构化克隆算法。
    • 通过在 Worker.postMessage() 或 ServiceWorker.postMessage() 的调用中传入 ArrayBuffer 对象作为可转移对象来完成。
    • 在纯 JavaScript 中,也可以使用 transfer() 或 transferToFixedLength() 方法来转移内存的所有权。
  2. 当一个 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()

  • 描述:调整为指定的大小,以字节为单位。
    1. 将 ArrayBuffer 调整为 newLength 参数指定的大小,前提是该 ArrayBuffer 是可调整大小的并且新的大小小于或等于该 ArrayBuffer 的 maxByteLength。新字节被初始化为 0。
    2. 注意,你可以使用 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 对象,该对象与此缓冲区具有相同的字节内容,然后将此缓冲区分离。