缓冲区和 TypedArray


¥Buffers and TypedArrays

Buffer 实例也是 JavaScript <Uint8Array><TypedArray> 实例。所有 <TypedArray> 方法都可用于 Buffer。但是,Buffer API 和 <TypedArray> API 之间存在细微的不兼容。

¥Buffer instances are also JavaScript <Uint8Array> and <TypedArray> instances. All <TypedArray> methods are available on Buffers. There are, however, subtle incompatibilities between the Buffer API and the <TypedArray> API.

特别是:

¥In particular:

有两种方式可以从 Buffer 创建新的 <TypedArray> 实例:

¥There are two ways to create new <TypedArray> instances from a Buffer:

  • Buffer 传递给 <TypedArray> 构造函数将复制 Buffer 内容,解释为整数数组,而不是目标类型的字节序列。

    ¥Passing a Buffer to a <TypedArray> constructor will copy the Buffers contents, interpreted as an array of integers, and not as a byte sequence of the target type.

import { Buffer } from 'node:buffer';

const buf = Buffer.from([1, 2, 3, 4]);
const uint32array = new Uint32Array(buf);

console.log(uint32array);

// Prints: Uint32Array(4) [ 1, 2, 3, 4 ]const { Buffer } = require('node:buffer');

const buf = Buffer.from([1, 2, 3, 4]);
const uint32array = new Uint32Array(buf);

console.log(uint32array);

// Prints: Uint32Array(4) [ 1, 2, 3, 4 ]
import { Buffer } from 'node:buffer';

const buf = Buffer.from('hello', 'utf16le');
const uint16array = new Uint16Array(
  buf.buffer,
  buf.byteOffset,
  buf.length / Uint16Array.BYTES_PER_ELEMENT);

console.log(uint16array);

// Prints: Uint16Array(5) [ 104, 101, 108, 108, 111 ]const { Buffer } = require('node:buffer');

const buf = Buffer.from('hello', 'utf16le');
const uint16array = new Uint16Array(
  buf.buffer,
  buf.byteOffset,
  buf.length / Uint16Array.BYTES_PER_ELEMENT);

console.log(uint16array);

// Prints: Uint16Array(5) [ 104, 101, 108, 108, 111 ]

通过以相同的方式使用 TypedArray 对象的 .buffer 属性,可以创建与 <TypedArray> 实例共享相同分配内存的新 BufferBuffer.from() 在这种情况下表现得像 new Uint8Array()

¥It is possible to create a new Buffer that shares the same allocated memory as a <TypedArray> instance by using the TypedArray object's .buffer property in the same way. Buffer.from() behaves like new Uint8Array() in this context.

import { Buffer } from 'node:buffer';

const arr = new Uint16Array(2);

arr[0] = 5000;
arr[1] = 4000;

// Copies the contents of `arr`.
const buf1 = Buffer.from(arr);

// Shares memory with `arr`.
const buf2 = Buffer.from(arr.buffer);

console.log(buf1);
// Prints: <Buffer 88 a0>
console.log(buf2);
// Prints: <Buffer 88 13 a0 0f>

arr[1] = 6000;

console.log(buf1);
// Prints: <Buffer 88 a0>
console.log(buf2);
// Prints: <Buffer 88 13 70 17>const { Buffer } = require('node:buffer');

const arr = new Uint16Array(2);

arr[0] = 5000;
arr[1] = 4000;

// Copies the contents of `arr`.
const buf1 = Buffer.from(arr);

// Shares memory with `arr`.
const buf2 = Buffer.from(arr.buffer);

console.log(buf1);
// Prints: <Buffer 88 a0>
console.log(buf2);
// Prints: <Buffer 88 13 a0 0f>

arr[1] = 6000;

console.log(buf1);
// Prints: <Buffer 88 a0>
console.log(buf2);
// Prints: <Buffer 88 13 70 17>

使用 <TypedArray>.buffer 创建 Buffer 时,可以通过传入 byteOffsetlength 参数仅使用底层 <ArrayBuffer> 的一部分。

¥When creating a Buffer using a <TypedArray>'s .buffer, it is possible to use only a portion of the underlying <ArrayBuffer> by passing in byteOffset and length parameters.

import { Buffer } from 'node:buffer';

const arr = new Uint16Array(20);
const buf = Buffer.from(arr.buffer, 0, 16);

console.log(buf.length);
// Prints: 16const { Buffer } = require('node:buffer');

const arr = new Uint16Array(20);
const buf = Buffer.from(arr.buffer, 0, 16);

console.log(buf.length);
// Prints: 16

Buffer.from()TypedArray.from() 具有不同的签名和实现。具体来说,<TypedArray> 变体接受第二个参数,该参数是在类型化数组的每个元素上调用的映射函数:

¥The Buffer.from() and TypedArray.from() have different signatures and implementations. Specifically, the <TypedArray> variants accept a second argument that is a mapping function that is invoked on every element of the typed array:

  • TypedArray.from(source[, mapFn[, thisArg]])

但是,Buffer.from() 方法不支持使用映射函数:

¥The Buffer.from() method, however, does not support the use of a mapping function: