DataView

DataView 视图提供了一个底层接口,用于读取和写入二进制 ArrayBuffer 中的多种数字类型,而无需关心平台的 endianness

¥The DataView view provides a low-level interface for reading and writing multiple number types in a binary ArrayBuffer, without having to care about the platform's endianness.

描述

¥Description

字节顺序

¥Endianness

根据机器架构的不同,多字节数字格式在内存中的表示方式也有所不同 - 请参阅 字节顺序 获取解释。DataView 访问器提供对数据访问方式的显式控制,无论执行计算机的字节顺序如何。例如,WebAssembly 内存始终是小端的,因此你应该使用 DataView 而不是类型化数组来读取和写入多字节值。请参阅 WebAssembly.Memory 的示例。

¥Multi-byte number formats are represented in memory differently depending on machine architecture — see Endianness for an explanation. DataView accessors provide explicit control of how data is accessed, regardless of the executing computer's endianness. For example, WebAssembly memory is always little-endian, so you should use DataView instead of typed arrays to read and write multi-byte values. See WebAssembly.Memory for an example.

js
const littleEndian = (() => {
  const buffer = new ArrayBuffer(2);
  new DataView(buffer).setInt16(0, 256, true /* littleEndian */);
  // Int16Array uses the platform's endianness.
  return new Int16Array(buffer)[0] === 256;
})();
console.log(littleEndian); // true or false

注意:DataView 默认为大端读写,但大多数平台使用小端。

¥Note: DataView defaults to big-endian read and write, but most platforms use little-endian.

64 位整数值

¥64-bit Integer Values

某些浏览器不支持 DataView.prototype.setBigInt64()DataView.prototype.setBigUint64()。因此,要在代码中启用可跨浏览器运行的 64 位操作,你可以实现自己的 getUint64() 函数,以获取精度高达 Number.MAX_SAFE_INTEGER 的值 — 这对于某些情况来说可能就足够了。

¥Some browsers don't have support for DataView.prototype.setBigInt64() and DataView.prototype.setBigUint64(). So to enable 64-bit operations in your code that will work across browsers, you could implement your own getUint64() function, to obtain values with precision up to Number.MAX_SAFE_INTEGER — which could suffice for certain cases.

js
function getUint64(dataview, byteOffset, littleEndian) {
  // split 64-bit number into two 32-bit (4-byte) parts
  const left = dataview.getUint32(byteOffset, littleEndian);
  const right = dataview.getUint32(byteOffset + 4, littleEndian);

  // combine the two 32-bit values
  const combined = littleEndian
    ? left + 2 ** 32 * right
    : 2 ** 32 * left + right;

  if (!Number.isSafeInteger(combined))
    console.warn(combined, "exceeds MAX_SAFE_INTEGER. Precision may be lost");

  return combined;
}

或者,如果你需要完整的 64 位范围,你可以创建 BigInt。此外,尽管原生 BigInt 比用户级库的等效项快得多,但由于其可变大小的性质,BigInt 始终比 JavaScript 中的 32 位整数慢得多。

¥Alternatively, if you need full 64-bit range, you can create a BigInt. Further, although native BigInts are much faster than user-land library equivalents, BigInts will always be much slower than 32-bit integers in JavaScript due to the nature of their variable size.

js
const BigInt = window.BigInt,
  bigThirtyTwo = BigInt(32),
  bigZero = BigInt(0);
function getUint64BigInt(dataview, byteOffset, littleEndian) {
  // split 64-bit number into two 32-bit (4-byte) parts
  const left = BigInt(dataview.getUint32(byteOffset | 0, !!littleEndian) >>> 0);
  const right = BigInt(
    dataview.getUint32(((byteOffset | 0) + 4) | 0, !!littleEndian) >>> 0,
  );

  // combine the two 32-bit values and return
  return littleEndian
    ? (right << bigThirtyTwo) | left
    : (left << bigThirtyTwo) | right;
}

构造函数

¥Constructor

DataView()

创建一个新的 DataView 对象。

实例属性

¥Instance properties

这些属性在 DataView.prototype 上定义并由所有 DataView 实例共享。

¥These properties are defined on DataView.prototype and shared by all DataView instances.

DataView.prototype.buffer

此视图引用的 ArrayBuffer。在构建时固定,因此只读。

DataView.prototype.byteLength

该视图的长度(以字节为单位)。在构建时固定,因此只读。

DataView.prototype.byteOffset

该视图相对于 ArrayBuffer 开头的偏移量(以字节为单位)。在构建时固定,因此只读。

DataView.prototype.constructor

创建实例对象的构造函数。对于 DataView 实例,初始值为 DataView 构造函数。

DataView.prototype[Symbol.toStringTag]

[Symbol.toStringTag] 属性的初始值为字符串 "DataView"。该属性在 Object.prototype.toString() 中使用。

实例方法

¥Instance methods

DataView.prototype.getBigInt64()

从该 DataView 的指定字节偏移量开始读取 8 个字节,并将它们解释为 64 位有符号整数。

DataView.prototype.getBigUint64()

从该 DataView 的指定字节偏移量开始读取 8 个字节,并将它们解释为 64 位无符号整数。

DataView.prototype.getFloat16()

从此 DataView 的指定字节偏移量开始读取 2 个字节,并将其解释为 16 位浮点数。

DataView.prototype.getFloat32()

从该 DataView 的指定字节偏移量开始读取 4 个字节,并将其解释为 32 位浮点数。

DataView.prototype.getFloat64()

从该 DataView 的指定字节偏移量开始读取 8 个字节,并将其解释为 64 位浮点数。

DataView.prototype.getInt16()

从该 DataView 的指定字节偏移量开始读取 2 个字节,并将它们解释为 16 位有符号整数。

DataView.prototype.getInt32()

从该 DataView 的指定字节偏移量开始读取 4 个字节,并将它们解释为 32 位有符号整数。

DataView.prototype.getInt8()

在此 DataView 的指定字节偏移处读取 1 个字节,并将其解释为 8 位有符号整数。

DataView.prototype.getUint16()

从该 DataView 的指定字节偏移量开始读取 2 个字节,并将它们解释为 16 位无符号整数。

DataView.prototype.getUint32()

从该 DataView 的指定字节偏移量开始读取 4 个字节,并将它们解释为 32 位无符号整数。

DataView.prototype.getUint8()

在此 DataView 的指定字节偏移处读取 1 个字节,并将其解释为 8 位无符号整数。

DataView.prototype.setBigInt64()

获取 BigInt 并将其作为 64 位有符号整数存储在从该 DataView 的指定字节偏移量开始的 8 个字节中。

DataView.prototype.setBigUint64()

获取 BigInt 并将其作为 64 位无符号整数存储在从该 DataView 的指定字节偏移量开始的 8 个字节中。

DataView.prototype.setFloat16()

获取一个数字并将其作为 16 位浮点数存储在从此 DataView 的指定字节偏移量开始的 2 个字节中。

DataView.prototype.setFloat32()

获取一个数字并将其作为 32 位浮点数存储在从该 DataView 的指定字节偏移量开始的 4 个字节中。

DataView.prototype.setFloat64()

获取一个数字并将其作为 64 位浮点数存储在从该 DataView 的指定字节偏移量开始的 8 个字节中。

DataView.prototype.setInt16()

获取一个数字并将其作为 16 位有符号整数存储在该 DataView 的指定字节偏移处的 2 个字节中。

DataView.prototype.setInt32()

获取一个数字并将其作为 32 位有符号整数存储在 DataView 的指定字节偏移处的 4 个字节中。

DataView.prototype.setInt8()

获取一个数字并将其作为 8 位有符号整数存储在该 DataView 的指定字节偏移处的字节中。

DataView.prototype.setUint16()

获取一个数字并将其作为 16 位无符号整数存储在该 DataView 的指定字节偏移处的 2 个字节中。

DataView.prototype.setUint32()

获取一个数字并将其作为 32 位无符号整数存储在 DataView 的指定字节偏移处的 4 个字节中。

DataView.prototype.setUint8()

获取一个数字并将其作为 8 位无符号整数存储在该 DataView 的指定字节偏移处的字节中。

示例

¥Examples

使用数据视图

¥Using DataView

js
const buffer = new ArrayBuffer(16);
const view = new DataView(buffer, 0);

view.setInt16(1, 42);
view.getInt16(1); // 42

规范

Specification
ECMAScript Language Specification
# sec-dataview-objects

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看