缓冲区与 TypedArray
Buffer 实例也是 JavaScript Uint8Array 和 TypedArray 实例。
所有 TypedArray 方法都可在 Buffer 上使用。
但是,Buffer API 和 TypedArray API 之间存在细微的不兼容。
特别是:
TypedArray.prototype.slice()创建TypedArray部分的副本,而Buffer.prototype.slice()在现有Buffer上创建视图而不进行复制。 这种行为可能会有意外,并且仅存在于旧版兼容性中。TypedArray.prototype.subarray()可用于在Buffer和其他TypedArray上实现Buffer.prototype.slice()的行为。buf.toString()与其对应的TypedArray不兼容。- 多种方法,例如
buf.indexOf(),支持额外的参数。
有两种方式可以从 Buffer 创建新的 TypedArray 实例:
- 将
Buffer传给TypedArray构造函数将复制Buffer的内容,解释为整数数组,而不是目标类型的字节序列。
const buf = Buffer.from([1, 2, 3, 4]);
const uint32array = new Uint32Array(buf);
console.log(uint32array);
// 打印: Uint32Array(4) [ 1, 2, 3, 4 ]- 传入
ArrayBuffer底层的Buffer将创建与Buffer共享其内存的TypedArray。
const buf = Buffer.from('hello', 'utf16le');
const uint16array = new Uint16Array(
buf.buffer,
buf.byteOffset,
buf.length / Uint16Array.BYTES_PER_ELEMENT);
console.log(uint16array);
// 打印: Uint16Array(5) [ 104, 101, 108, 108, 111 ]通过以相同的方式使用 TypedArray 对象的 .buffer 属性,可以创建新的 Buffer,它与 TypedArray 实例共享相同的分配内存。
Buffer.from() 在这种情况下表现得像 new Uint8Array()。
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 时,可以通过传入 byteOffset 和 length 参数仅使用底层 ArrayBuffer 的一部分。
const arr = new Uint16Array(20);
const buf = Buffer.from(arr.buffer, 0, 16);
console.log(buf.length);
// 打印: 16Buffer.from() 和 TypedArray.from() 具有不同的签名和实现。
具体来说,TypedArray 变体接受第二个参数,该参数是在类型化数组的每个元素上调用的映射函数:
TypedArray.from(source[, mapFn[, thisArg]])
但是,Buffer.from() 方法不支持使用映射函数:
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:
- While
TypedArray.prototype.slice()creates a copy of part of theTypedArray,Buffer.prototype.slice()creates a view over the existingBufferwithout copying. This behavior can be surprising, and only exists for legacy compatibility.TypedArray.prototype.subarray()can be used to achieve the behavior ofBuffer.prototype.slice()on bothBuffers and otherTypedArrays. buf.toString()is incompatible with itsTypedArrayequivalent.- A number of methods, e.g.
buf.indexOf(), support additional arguments.
There are two ways to create new TypedArray instances from a Buffer:
- Passing a
Bufferto aTypedArrayconstructor will copy theBuffers contents, interpreted as an array of integers, and not as a byte sequence of the target type.
const buf = Buffer.from([1, 2, 3, 4]);
const uint32array = new Uint32Array(buf);
console.log(uint32array);
// Prints: Uint32Array(4) [ 1, 2, 3, 4 ]- Passing the
Buffers underlyingArrayBufferwill create aTypedArraythat shares its memory with theBuffer.
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 ]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.
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>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: 16The 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: