Buffer 与 TypedArray


Buffer 实例也是 Uint8Array 实例,但是与 TypedArray 有微小的不同。 例如,ArrayBuffer#slice() 会创建切片的拷贝,而 Buffer#slice() 是在现有的 Buffer 上创建而不拷贝。

使用 TypeArray.buffer 属性可以创建一个与其共享内存的 Buffer

const arr = new Uint16Array(2);

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

// 拷贝 `arr` 的内容。
const buf1 = Buffer.from(arr);
// 与 `arr` 共享内存。
const buf2 = Buffer.from(arr.buffer);

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

arr[1] = 6000;

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

当使用 TypedArray.buffer 创建 Buffer 时,也可以通过传入 byteOffsetlength 参数只使用 ArrayBuffer 的一部分。

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

console.log(buf.length);
// 输出: 16

Buffer.from()TypedArray.from() 有着不同的实现。 TypedArray 可以有映射函数,对类型数组的每个元素各调用一次:

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

Buffer.from() 不支持映射函数:

Buffer instances are also Uint8Array instances. However, there are subtle incompatibilities with TypedArray. For example, while ArrayBuffer#slice() creates a copy of the slice, the implementation of Buffer#slice() creates a view over the existing Buffer without copying, making Buffer#slice() far more efficient.

It is also possible to create new TypedArray instances from a Buffer with the following caveats:

  1. The Buffer object's memory is copied to the TypedArray, not shared.

  2. The Buffer object's memory is interpreted as an array of distinct elements, and not as a byte array of the target type. That is, new Uint32Array(Buffer.from([1, 2, 3, 4])) creates a 4-element Uint32Array with elements [1, 2, 3, 4], not a Uint32Array with a single element [0x1020304] or [0x4030201].

It is possible to create a new Buffer that shares the same allocated memory as a TypedArray instance by using the TypeArray object's .buffer property.

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>

Note that 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.

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

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

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]])

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