【lib.es5】ArrayBuffer、DataView 的TypeScript接口

本文涉及的产品
可视分析地图(DataV-Atlas),3 个项目,100M 存储空间
简介: 【lib.es5】ArrayBuffer、DataView 的TypeScript接口

ArrayBuffer、DataView 的 TypeScript 接口


1. ArrayBuffer

ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。

它是一个字节数组,通常在其他语言中称为“byte array”。

不能直接操作 ArrayBuffer 的内容,而是要通过 类型数组对象 或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。

1.1 语法

new ArrayBuffer(length)
  • length: 要创建的 ArrayBuffer 的大小,单位为字节。

1.1.1 返回值

一个指定大小的 ArrayBuffer 对象,其内容被初始化为 0。

1.1.2 异常

如果 length 大于 Number.MAX_SAFE_INTEGER(>= 2 ** 53)或为负数,则抛出一个 RangeError 异常。

ArrayBuffer 构造函数用来创建一个指定字节长度的 ArrayBuffer 对象。

1.2 描述

1.2.1 属性

属性 描述
ArrayBuffer.length ArrayBuffer 构造函数的 length 属性,其值为1。
ArrayBuffer.prototype.byteLength 只读属性,表示 ArrayBuffer 的byte的大小,在ArrayBuffer构造完成时生成,不可改变。
get ArrayBuffer[@@species] 返回 ArrayBuffer 的构造函数。
ArrayBuffer.prototype (en-US) 通过 ArrayBuffer 的原型对象可以为所有 ArrayBuffer 对象添加属性。

1.2.2 方法

方法 描述
ArrayBuffer.isView(arg) 如果参数是 ArrayBuffer 的视图实例则返回 true,例如 类型数组对象 或 DataView 对象;否则返回 false。
ArrayBuffer.transfer(oldBuffer [, newByteLength]) (实验性的) 返回一个新的 ArrayBuffer 对象,其内容取自 oldBuffer 中的数据,并且根据 newByteLength 的大小对数据进行截取或补 0。

1.2.3 JavaScript 示例

下面的例子创建了一个 8 字节的缓冲区,并使用一个 Int32Array 来引用它:

var buffer = new ArrayBuffer(8);
var view   = new Int32Array(buffer);

1.2.4 TypeScript 接口

/**
 * 表示二进制数据的原始缓冲区,用于存储不同类型数组的数据。
 * ArrayBuffers不能直接读取或写入,但可以传递给类型化数组或DataView对象,以便根据需要解释原始缓冲区。
 */
interface ArrayBuffer {
    /**
     * 只读。ArrayBuffer的长度(字节)。
     */
    readonly byteLength: number;
    /**
     * 返回ArrayBuffer的一部分。
     */
    slice(begin: number, end?: number): ArrayBuffer;
}
/**
 * ArrayBufferView和相关类型化数组的缓冲区允许的ArrayBuffer类型。
 */
interface ArrayBufferTypes {
    ArrayBuffer: ArrayBuffer;
}
type ArrayBufferLike = ArrayBufferTypes[keyof ArrayBufferTypes];
interface ArrayBufferConstructor {
    readonly prototype: ArrayBuffer;
    new(byteLength: number): ArrayBuffer;
    isView(arg: any): arg is ArrayBufferView;
}
declare var ArrayBuffer: ArrayBufferConstructor;
interface ArrayBufferView {
    /**
     * 数组引用的ArrayBuffer实例。
     */
    buffer: ArrayBufferLike;
    /**
     * 数组的字节长度。
     */
    byteLength: number;
    /**
     * 数组的偏移量,以字节为单位。
     */
    byteOffset: number;
}

2. DataView

DataView 视图是一个可以从 二进制ArrayBuffer 对象中读写多种数值类型的底层接口,使用它时,不用考虑不同平台的字节序问题。

2.1 语法

new DataView(buffer [, byteOffset [, byteLength]])
  • buffer 一个 已经存在的ArrayBuffer 或 SharedArrayBuffer 对象,DataView 对象的数据源。
  • byteOffset 可选,该 DataView 对象的第一个字节在 buffer 中的字节偏移。如果未指定,则默认从第一个字节开始。
  • byteLength 可选,该 DataView 对象的第一个字节在 buffer 中的字节偏移。如果未指定,则默认从第一个字节开始。

返回值

一个表示指定数据缓存区的新DataView 对象。(这句话也许不是非常有助于说明清楚)

你可以把返回的对象想象成一个二进制字节缓存区 array buffer 的“解释器”——它知道如何在读取或写入时正确地转换字节码。这意味着它能在二进制层面处理整数与浮点转化、字节顺序等其他有关的细节问题。

异常

RangeError

如果 byteOffset 或者 byteLength 参数的值导致视图超出了 buffer 的结束位置就会抛出此异常。

例如,假设 buffer (缓冲对象)是 16 字节长度,byteOffset 参数为 8,byteLength 参数为 10,这个错误就会抛出,这是因为结果视图试图超出 buffer 对象的总长度 2 个字节。

2.2 描述

2.2.1 Endianness(字节序)

需要多个字节来表示的数值,在存储时其字节在内存中的相对顺序依据平台架构的不同而不同。

字节序,或字节顺序(“Endian”、“endianness” 或 “byte-order”),描述了计算机如何组织字节,组成对应的数字。

每个内存存储位置都有一个索引或地址。每一 字节可以存储一个8位数字(即 介于0x00 和 0xff 之间)。

因此,你必须保留不止一个字节来储存一个更大的数字。现在,大部分需占用多个字节的数字排序方式是 little-endian(译者注:可称小字节序、低字节序,即低位字节排放在内存的低地址端,高位字节排放在内存的高地址端。

与之对应的 big-endian 排列方式相反,可称大字节序、高字节序),所有的英特尔处理器都使用 little-endian。little-endian 的意思是使用低位储存更重要的信息,least-to-most-significant(最不重要的(least significant)字节取第一个位置,或者说地址最低的位置),可类比欧洲通用的日期书写方式(例如,31 December 2050。译者注:年份是最重要的,月份其次,日期最后)。

自然, big-endian 是相反的顺序, 可类比 ISO 日期格式(例如 2050-12-31)。big-endian 通常被称作"网络字节顺序"(“network byte order”), 因为互联网标准通常要求数据使用 big-endian 存储,从标准 Unix 套接字(socket)层开始,一直到标准化网络的二进制数据结构。此外,老式 Mac 计算机的 68000 系列 和 PowerPC(译者注:IBM 与 Apple 公司联合生产的个人台式机)微处理器曾使用 big-endian。

如:用不同字节序存储数字 0x12345678(即十进制中的 305 419 896):

little-endian:0x78 0x56 0x34 0x12

big-endian:0x12 0x34 0x56 0x78

var littleEndian = (function() {
  var buffer = new ArrayBuffer(2);
  new DataView(buffer).setInt16(0, 256, true /* 设置值时,使用小端字节序 */);
  // Int16Array 使用系统字节序(由此可以判断系统字节序是否为小端字节序)
  return new Int16Array(buffer)[0] === 256;
})();
console.log(littleEndian); // 返回 true 或 false

2.2.2 位整数值

因为 JavaScript 目前不包含对 64 位整数值支持的标准,所以 DataView 不提供原生的 64 位操作。作为变通,您可以实现自己的 getUint64() 函数,以获得精度高达 Number.MAX_SAFE_INTEGER 的值,可以满足某些特定情况的需求。

function getUint64(dataview, byteOffset, littleEndian) {
  // 将 64 位整数值分成两份 32 位整数值
  const left =  dataview.getUint32(byteOffset, littleEndian);
  const right = dataview.getUint32(byteOffset+4, littleEndian);
  // 合并两个 32 位整数值
  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 中,BigInt 总是比 32 位整数慢得多,这是因为 BigInt 的大小是可变的。

const BigInt = window.BigInt, bigThirtyTwo = BigInt(32), bigZero = BigInt(0);
function getUint64BigInt(dataview, byteOffset, littleEndian) {
  // 将 64 位整数值分成两份 32 位整数值
  const left = BigInt(dataview.getUint32(byteOffset|0, !!littleEndian)>>>0);
  const right = BigInt(dataview.getUint32((byteOffset|0) + 4|0, !!littleEndian)>>>0);
  // 合并两个 32 位整数值并返回
  return littleEndian ? (right<<bigThirtyTwo)|left : (left<<bigThirtyTwo)|right;
}

2.2.3 构造器、属性与方法

所有 DataView 实例都继承自 DataView.prototype,并且允许向 DataView 对象中添加额外属性。

2.2.3.1 构造器

DataView(): 创建新的DataView对象。

2.2.3.2 实例属性
属性 描述
DataView.prototype.buffer 此视图引用的ArrayBuffer。在构造时固定,因此是只读的。
DataView.prototype.byteLength 此视图从其ArrayBuffer开始的长度(以字节为单位)。在构造时固定,因此是只读的。
DataView.prototype.byteOffset 此视图从其ArrayBuffer开始的偏移量(以字节为单位)。在构造时固定,因此是只读的。
2.2.3.3 实例方法
方法 描述
DataView.prototype.getInt8() 从视图开始处的指定字节偏移量处获取一个有符号的8位整数(字节)。
DataView.prototype.getUint8() 从视图开始处的指定字节偏移量处获取一个无符号8位整数(无符号字节)。
DataView.prototype.getInt16() 从视图开始处的指定字节偏移量处获取一个有符号的16位整数(短整型)。
DataView.prototype.getUint16() 从视图开始处的指定字节偏移量处获取一个无符号16位整数(无符号短整型)。
DataView.prototype.getInt32() 从视图开始处的指定字节偏移量处获取一个有符号的32位整数(长整型)。
DataView.prototype.getUint32() 从视图开始处的指定字节偏移量处获取一个无符号32位整数(无符号长整型)。
DataView.prototype.getFloat32() 从视图开始处的指定字节偏移量处获取一个带符号的32位浮点(float)。
DataView.prototype.getFloat64() 从视图开始处的指定字节偏移量处获取一个带符号的64位浮点型(双精度)。
DataView.prototype.getBigInt64() 从视图开始处的指定字节偏移量处获取一个带符号的64位整数(长整型)。
DataView.prototype.getBigUint64() 从视图开始处的指定字节偏移量处获取一个无符号64位整数(无符号长整型)。
DataView.prototype.setInt8() 在距视图开头的指定字节偏移量处存储一个有符号的8位整数(字节)值。
DataView.prototype.setUint8() 在距视图开头的指定字节偏移量处存储一个无符号8位整数(无符号字节)值。
DataView.prototype.setInt16() 在距视图开始处的指定字节偏移量处存储一个有符号的16位整数(短整型)值。
DataView.prototype.setUint16() 在距视图开头的指定字节偏移量处存储一个无符号16位整数(无符号短整型)值。
DataView.prototype.setInt32() 在距视图开头的指定字节偏移量处存储一个有符号的32位整数(长整型)值。
DataView.prototype.setUint32() 在距视图开头的指定字节偏移量处存储一个无符号32位整数(无符号长整型)值。
DataView.prototype.setFloat32() 在距视图开头的指定字节偏移量处存储一个带符号的32位浮点(float)值。
DataView.prototype.setFloat64() 在距视图开头的指定字节偏移量处存储一个带符号的64位浮点(双精度)值。
DataView.prototype.setBigInt64() 在距视图开头的指定字节偏移量处存储一个带符号的64位整数值(long long)。
DataView.prototype.setBigUint64() 在距视图开头的指定字节偏移量处存储一个无符号64位整数值(无符号长整型)。

2.2.4 JavaScript 示例

var buffer = new ArrayBuffer(16);
var view = new DataView(buffer, 0);
view.setInt16(1, 42);
view.getInt16(1); // 42

2.2.5 TypeScript 接口

interface DataView {
    readonly buffer: ArrayBuffer;
    readonly byteLength: number;
    readonly byteOffset: number;
    /**
     * 获取距视图开头指定字节偏移量处的Float32值。没有对齐约束;多字节值可以从任何偏移量获取。
     * @param byteOffset 缓冲区中应检索值的位置。
     */
    getFloat32(byteOffset: number, littleEndian?: boolean): number;
    /**
     * 从视图的开始处获取指定字节偏移量处的Float64值。没有对齐约束;多字节值可以从任何偏移量获取。
     * @param byteOffset 缓冲区中应检索值的位置。
     */
    getFloat64(byteOffset: number, littleEndian?: boolean): number;
    /**
     * 从视图的开始处获取指定字节偏移量处的Int8值。没有对齐约束;多字节值可以从任何偏移量获取。
     * @param byteOffset 缓冲区中应检索值的位置。
     */
    getInt8(byteOffset: number): number;
    /**
     * 从视图的开始处获取指定字节偏移量处的Int16值。没有对齐约束;多字节值可以从任何偏移量获取。
     * @param byteOffset 缓冲区中应检索值的位置。
     */
    getInt16(byteOffset: number, littleEndian?: boolean): number;
    /**
     * 从视图的开始处获取指定字节偏移量处的Int32值。没有对齐约束;多字节值可以从任何偏移量获取。
     * @param byteOffset 缓冲区中应检索值的位置。
     */
    getInt32(byteOffset: number, littleEndian?: boolean): number;
    /**
     * 从视图的开始处获取指定字节偏移量处的Uint8值。没有对齐约束;多字节值可以从任何偏移量获取。
     * @param byteOffset 缓冲区中应检索值的位置。
     */
    getUint8(byteOffset: number): number;
    /**
     * 从视图的开始处获取指定字节偏移量处的Uint16值。没有对齐约束;多字节值可以从任何偏移量获取。
     * @param byteOffset 缓冲区中应检索值的位置。
     */
    getUint16(byteOffset: number, littleEndian?: boolean): number;
    /**
     * 从视图的开始处获取指定字节偏移量处的Uint32值。没有对齐约束;多字节值可以从任何偏移量获取。
     * @param byteOffset 缓冲区中应检索值的位置。
     */
    getUint32(byteOffset: number, littleEndian?: boolean): number;
    /**
     * 在距视图开头的指定字节偏移量处存储Float32值。
     * @param byteOffset 缓冲区中应该设置值的位置。
     * @param value 要设置的值。
     * @param littleEndian 如果为 false 或 undefined,则应写入大端值,否则应写入小端值。
     */
    setFloat32(byteOffset: number, value: number, littleEndian?: boolean): void;
    /**
     * 在距视图开始处的指定字节偏移量处存储一个Float64值。
     * @param byteOffset 缓冲区中应该设置值的位置。
     * @param value 要设置的值。
     * @param littleEndian 如果为 false 或 undefined,则应写入大端值,否则应写入小端值。
     */
    setFloat64(byteOffset: number, value: number, littleEndian?: boolean): void;
    /**
     * 在距视图开始处的指定字节偏移量处存储一个Int8值。
     * @param byteOffset 缓冲区中应该设置值的位置。
     * @param value 要设置的值。
     */
    setInt8(byteOffset: number, value: number): void;
    /**
     * 在距视图开始处的指定字节偏移量处存储一个Int16值。
     * @param byteOffset 缓冲区中应该设置值的位置。
     * @param value 要设置的值。
     * @param littleEndian 如果为 false 或 undefined,则应写入大端值,否则应写入小端值。
     */
    setInt16(byteOffset: number, value: number, littleEndian?: boolean): void;
    /**
     * 在距视图开始处的指定字节偏移量处存储一个Int32值。
     * @param byteOffset 缓冲区中应该设置值的位置。
     * @param value 要设置的值。
     * @param littleEndian 如果为 false 或 undefined,则应写入大端值,否则应写入小端值。
     */
    setInt32(byteOffset: number, value: number, littleEndian?: boolean): void;
    /**
     * 在距视图开始处的指定字节偏移量处存储一个Uint8值。
     * @param byteOffset 缓冲区中应该设置值的位置。
     * @param value 要设置的值。
     */
    setUint8(byteOffset: number, value: number): void;
    /**
     * 在距视图开头的指定字节偏移量处存储一个Uint16值。
     * @param byteOffset 缓冲区中应该设置值的位置。
     * @param value 要设置的值。
     * @param littleEndian 如果为 false 或 undefined,则应写入大端值,否则应写入小端值。
     */
    setUint16(byteOffset: number, value: number, littleEndian?: boolean): void;
    /**
     * 在距视图开头的指定字节偏移量处存储一个Uint32值。
     * @param byteOffset 缓冲区中应该设置值的位置。
     * @param value 要设置的值。
     * @param littleEndian 如果为 false 或 undefined,则应写入大端值,否则应写入小端值。
     */
    setUint32(byteOffset: number, value: number, littleEndian?: boolean): void;
}
相关实践学习
DataV Board用户界面概览
本实验带领用户熟悉DataV Board这款可视化产品的用户界面
阿里云实时数仓实战 - 项目介绍及架构设计
课程简介 1)学习搭建一个数据仓库的过程,理解数据在整个数仓架构的从采集、存储、计算、输出、展示的整个业务流程。 2)整个数仓体系完全搭建在阿里云架构上,理解并学会运用各个服务组件,了解各个组件之间如何配合联动。 3&nbsp;)前置知识要求 &nbsp; 课程大纲 第一章&nbsp;了解数据仓库概念 初步了解数据仓库是干什么的 第二章&nbsp;按照企业开发的标准去搭建一个数据仓库 数据仓库的需求是什么 架构 怎么选型怎么购买服务器 第三章&nbsp;数据生成模块 用户形成数据的一个准备 按照企业的标准,准备了十一张用户行为表 方便使用 第四章&nbsp;采集模块的搭建 购买阿里云服务器 安装 JDK 安装 Flume 第五章&nbsp;用户行为数据仓库 严格按照企业的标准开发 第六章&nbsp;搭建业务数仓理论基础和对表的分类同步 第七章&nbsp;业务数仓的搭建&nbsp; 业务行为数仓效果图&nbsp;&nbsp;
目录
相关文章
|
7月前
|
JavaScript
​​​​Typescript 接口 和继承 数组处理
ts的基础数据类型,可用来处理一般数据,但是碰到后台传入的复杂对象数组的时候,我们可以使用ts中的接口来定义处理
65 0
|
7月前
|
JavaScript 前端开发 C++
Typescript.中文.接口声明.lib.es5.d.ts
Typescript.中文.接口声明.lib.es5.d.ts
55 0
|
3月前
|
JavaScript
typeScript基础(5)_对象的类型-interfaces接口
本文介绍了TypeScript中接口(interfaces)的基本概念和用法,包括如何定义接口、接口的简单使用、自定义属性、以及如何使用`readonly`关键字定义只读属性。接口在TypeScript中是定义对象形状的重要方式,可以规定对象的必有属性、可选属性、自定义属性和只读属性。
47 1
|
2月前
|
JavaScript 前端开发 Java
TypeScript【接口】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第10天】TypeScript【接口】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
3月前
|
数据采集 JavaScript 前端开发
使用 TypeScript 接口优化数据结构
使用 TypeScript 接口优化数据结构
|
4月前
|
开发框架 前端开发 JavaScript
在基于vue-next-admin的Vue3+TypeScript前端项目中,为了使用方便全局挂载对象接口
在基于vue-next-admin的Vue3+TypeScript前端项目中,为了使用方便全局挂载对象接口
|
5月前
|
JavaScript 开发者 索引
TypeScript接口与类型别名:深入解析与应用实践
【7月更文挑战第10天】TypeScript的接口和类型别名是定义类型的关键工具。接口描述对象结构,用于类、对象和函数参数的形状约束,支持可选、只读属性及继承。类型别名则为复杂类型提供新名称,便于重用和简化。接口适合面向对象场景,类型别名在类型重用和复杂类型简化时更有优势。选择时要考虑场景和灵活性。
|
4月前
|
JavaScript 前端开发 API
Vue 3+TypeScript项目实战:解锁vue-next-admin中的全局挂载对象接口,让跨组件共享变得高效而优雅!
【8月更文挑战第3天】在构建Vue 3与TypeScript及vue-next-admin框架的应用时,为提高多组件间共享数据或方法的效率和可维护性,全局挂载对象接口成为关键。本文通过问答形式介绍其必要性和实现方法:首先定义全局接口及其实现,如日期格式化工具;接着在`main.ts`中通过`app.config.globalProperties`将其挂载;最后在组件内通过Composition API的`getCurrentInstance`访问。这种方式简化了跨组件通信,增强了代码复用性和维护性。
67 0
|
6月前
|
JavaScript 索引 前端开发
9.【TypeScript 教程】接口(Interface)
9.【TypeScript 教程】接口(Interface)
65 4
|
5月前
|
JavaScript 前端开发 程序员
Typescript 【实用教程】(2024最新版)含类型声明,类型断言,函数,接口,泛型等
Typescript 【实用教程】(2024最新版)含类型声明,类型断言,函数,接口,泛型等
91 0