ES6 中的 TypedArray 数据类型详解

在 JavaScript 编程中,TypedArray 作为数据类型是比较常用的。这种数据类型的出现只是为了能够更方便地操作二进制数据。它提供了一种可以用来认定视图的构造函数,得以读入已知的类型,而不是十六进制数值的数组。下面我们就来一一学习 ES6 中的 TypedArray 数据类型。

1. TypedArray

TypedArray 是指一种只含有成员为特定数据类型的数组,其中特定数据类型是由 TypedArray 类型定义的。该类型有以下几个常用的子类型:

  • Int8Array:8 位有符号整数
  • Uint8Array:8 位无符号整数
  • Uint8ClampedArray:8 位无符号整数(有约束)
  • Int16Array:16 位有符号整数
  • Uint16Array:16 位无符号整数
  • Int32Array:32 位有符号整数
  • Uint32Array:32 位无符号整数
  • Float32Array:32 位浮点数
  • Float64Array:64 位浮点数

我们需要注意的是,TypedArray 只能包含一个特定的数据类型,而不能同时包含多个不同类型的数据。

实现 TypedArray 的方式在其子类型内是基本一致的。在使用它们之前,必须要区分在构造函数中指定的 Buffers/ArrayBuffers 来存储数据以及这些 Buffer/ArrayBuffer 的字节偏移量(Buffer 不需要这个偏移量的信息)。

在 ES6 中使用 TypedArray 的一个常见的场景是处理音视频 Flow 的二进制数据。

2. Buffer/ArrayBuffer 特性

TypedArray 可以接受 ArrayBuffer 或 Buffer 这两个类型的数据源。 ArrayBuff 是一种可以让 TypedArray 映射到内存的字节数组,是无法直接使用的。而 Buffer 是 Node.js 赋予 JavaScript 的 Buffer 类,能够更加友好地支持二进制数据操作。

下面我们就来了解一下这两个类型的特性以及它们之间的区别。

2.1 ArrayBuffer

ArrayBuffer 是一个二进制数据缓存区,通常是不能直接操作的。如果你想在 ES5 或者之前的环境用 TypedArray 来读取二进制流,你需要自己实现 ArrayBuffer 的分配、增长、运维等。而到了 ES6 以后,基于 TypedArray 的语法糖就让 ArrayBuffer 操作变得简单了起来。

TypedArray 对 ArrayBuffer 实际上是要求对其进行一定程度的使用。其中,TypedArray 数组是在 ArrayBuffer 上导出的视图,以特定长度和字节偏移量构建出来的,可以直接读写 ArrayBuffer 的数据。

观察下面的代码:

--- ------ - --- ---------------
--- -------- - --- -----------------
------------------- ----
------------------- ------
--------------- --------------------

上面的代码会输出 [8250]。这个结果是因为在这个例子中新建了一个 ArrayBuffer 和其 DataView。这个 DataView 的字节偏移量是从 TextView 开始的。Int16Array 会在 TextView 内的数据上完成位序列从低位到高位的合成。

2.2 Buffer

Node.js 中的 Buffer 是对 ArrayBuffer 的再次包裹。我们可以通过使用如下代码创建一个 Buffer:

--- --- - --- -----------

注意,这个版本的 Buffer 是有一些安全风险的,因为它默认会对内存池进行可写可读的授权。具有可执行代码的 JPEG 或 PNG 的 header,如果在其中寄有一个故障,就有可能越过 Boundary 覆盖一些开了 W^X 属性的内存区塊,从而控制计算机的权限。

这个安全风险只出现在推荐的转码方式汇总,其中会在含有大量内存分配的场景下失控,比如 zlib 初始化阶段中的大量内存分配等。

在 Node.js v8.3 以后的版本中,Buffer 的创建方式推荐是:

----------------

这个方式是通过系统程序来初始化内存池,如果系统程序逊于 v8.3 或者没有可用的内存池,系统程序在调用 gc 的时候也会主动去通知系统释放规格超出大小阈值的 Buffer,更加健壮。使用 Buffer.alloc 返回的对象同样可以像 ArrayBuffer 一样被使用。

2.3 区别与应用场景

使用 ArrayBuffer 能够做的事情,使用 Buffer 和 TypedArray 也能够做到,反之亦然,区别在于它们的应用场景和性能上的差异。下面我们来探讨一下这两个不同类型之间的区别。

2.3.1 数组复制

Buffer 的特别之处是它可以很容易地对二进制数据进行读写,而无需进行任何的索引运算。Buffer 是在 EventEmitter 上以可读流和可写流的形式实现的,是 Node.js 标准库中的内置类型。它能够在将 Buffer 写到流中之前进行加工,比如: 添加压缩、加密。在读取流中的 Buffer 时能够进行相反的加工,比如解压、解密。 Buffer 类型本身也提供了很多的 API,这些 API 是一些方便使用和优化性能的小工具。

下面是一个使用 Buffer 的示例。这个代码会把同样的数据复制给三个新的 Buffer 对象。

----- ---- - -----------------
----- ---- - -------------------
----- ---- - -----------------------

2.3.2 Array 的行为

TypedArray 是通常在 GPU、硬件级别处理程序和高端音视频的引擎中才会用到的高级工具。它是对 Array 的补充,但二者有许多明显的差异。在 Array 上执行很多通用转换都是比较容易的,因为 Array 具有高度灵活性。

意味着很多从 TS 转换过来的遗产代码不需要太多的重构以支持 TypedArray。这时,我们可以使用 TypedArray 来避免因移动一段数据而带来的内存和时间成本。

下面我们使用 TypedArray 将数组乘以一个常数。

----- - - --- ----------------------
----- - - --- ---------------------

--- ---- - - -- - - --------- ---- -
  ---- - ---- - --
-
---------------

上面的代码会输出 [2,4,6,8]

总的来说,如果我们需要在标准的数组结构上再做一些有用的附加操作,这时候就要使用 TypedArray 来解决问题。

3. 总结

TypedArray 在处理二进制数据时能够发挥很大的作用,不过其原理和使用方法较为复杂。熟悉了 ES6 中 TypedArray 的相关知识后可以让我们在处理此类问题时更加得心应手。同时,我们能够针对实际问题判断何时使用 TypedArray 以及何时使用 ArrayBuffer 和 Buffer,这样能够更好地节省计算机资源和提高我们的代码运行效率。

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/64f95a7ff6b2d6eab30e08fc


猜你喜欢

  • Next.js 如何实现重定向?

    在前端项目开发中,重定向(Redirect)是一个非常常见的功能,用于将用户从一个 URL 地址自动导向到另外一个 URL 地址,通常在处理一些用户请求传递时会用到。

    1 年前
  • Promise 和回调函数的区别

    在前端开发中,经常需要处理异步操作,比如通过 Ajax 获取数据。在处理异步操作时,可以使用回调函数或 Promise。那么什么是回调函数和 Promise,它们有什么区别呢?在什么情况下该选择使用回...

    1 年前
  • Cypress 如何实现多个测试场景之间的数据共享

    Cypress 是一个流行的前端自动化测试框架,可以帮助开发人员编写高质量的端到端测试。在实际的测试过程中,我们可能需要在多个测试场景之间共享数据,以便更好地模拟真实场景。

    1 年前
  • TypeScript 中的极限类型转换

    TypeScript 中的极限类型转换 随着 JavaScript 的流行,TypeScript 也变得越来越普遍。TypeScript 不仅提供了语言层面上的类型检查,还提供了更多的开发工具和语法糖...

    1 年前
  • 在 ES12 中使用 Object.fromEntries() 方法

    在 ES12 中使用 Object.fromEntries() 方法 随着 JavaScript 的发展,每一次新版本的推出都会带来新的特性和 API。其中 ES12(也被称为 ES2021)中新增的...

    1 年前
  • Mongoose:使用管道查询大文档集合

    Mongoose 是一个 Node.js 下基于 MongoDB 的对象模型工具,为开发者提供了方便的数据操作。在 MongoDB 中,文档(Document)是最小的数据单元,而在实际开发过程中,我...

    1 年前
  • ES7 async/await 语句的 try-catch 捕获及处理思路

    在前端开发中,异步操作是很常见的一个场景。JavaScript 语言原生提供了 promise 对象来处理异步操作,ES7 标准中提供的 async/await 语句更可以在处理异步操作上提供更好的可...

    1 年前
  • 如何使用 Deno 进行错误处理?

    Deno 是一个现代的 JavaScript 和 TypeScript 运行时环境,它可以用于构建各种 Web 应用程序。在实际开发中,错误处理是一个非常关键的方面,因为它可以帮助我们快速识别和解决问...

    1 年前
  • Redis内存数据持久化方案详解

    Redis是一款基于内存的NoSQL数据库,它具有极高的性能和可扩展性,被广泛应用于Web应用的缓存、消息队列等领域。但由于内存容量有限,当Redis服务器重启或崩溃时,内存中的所有数据都会丢失。

    1 年前
  • CSS3 Flexbox 布局中的 flex-grow 属性详解

    在 CSS3 中引入了弹性盒子布局(Flexbox),可以帮助开发者更加方便地实现页面布局。其中,flex-grow 属性是比较常用的一个属性,本文将详细介绍该属性的使用方法和注意事项。

    1 年前
  • 解决响应式设计在移动设备上的兼容性问题

    随着移动设备的普及和使用,响应式设计已经成为了前端开发中不可或缺的一部分。但是,移动设备的屏幕尺寸和分辨率等问题往往会对响应式设计造成一定的兼容性问题。本文将介绍几种解决响应式设计在移动设备上兼容性问...

    1 年前
  • Linux 性能优化:应用程序性能诊断与调优流程

    在前端工作中,我们经常会使用各式各样的工具和技术来调试和优化我们的代码,以提升用户体验和响应速度。而在服务器端,特别是在 Linux 环境下,我们也需要关注应用程序的性能优化。

    1 年前
  • 如何在 React 中使用浏览器的 Local Storage

    在许多前端应用程序中,我们经常需要在浏览器中存储一些数据。 比如说我们想在用户下次访问我们的应用程序时保留他们的偏好设置,或者我们想在不刷新网页的情况下在不同的组件之间传递数据。

    1 年前
  • 在使用 Tailwind 时,如何处理媒体查询?

    Tailwind 是一个流行的 CSS 框架,能够极大地提高前端的开发效率。但是,在设计响应式网页时,我们不可避免地需要使用媒体查询来适配不同的设备屏幕。那么,当我们使用 Tailwind 框架时,如...

    1 年前
  • ES9 中的正则表达式命名捕获组使用示例

    正则表达式是前端开发中常用的工具。ES9 中的正则表达式增加了命名捕获组的功能,这个功能使得在判断某些拥有多个匹配捕获组的正则表达式时更加简洁方便。 命名捕获组 在 ES9 之前,捕获组都是用数字来表...

    1 年前
  • 实现基于 Node.js 的 RESTful API 服务的具体步骤

    实现基于 Node.js 的 RESTful API 服务的具体步骤 RESTful API 是一种基于 HTTP/HTTPS 协议的 API 设计风格,通过在请求 URL 中使用 HTTP 方法和 ...

    1 年前
  • SPA 应用中如何实现多语言切换

    单页应用 (SPA) 越来越流行,但是多语言支持是一个非常重要的问题。在大型多语言 SPA 应用中,为用户提供多种语言的选择可能是必要的,本文将介绍如何实现 SPA 应用的多语言支持。

    1 年前
  • 在 Mocha 测试框架中如何使用 Sinon 进行 Mock 和 Stub

    Sinon 是一个 JavaScript 测试框架,它提供了 mock、stub 和 spy 等工具,用于使测试更加便捷和可靠。在前端开发中,我们经常需要对各种异步调用进行测试,这时候 Sinon 可...

    1 年前
  • RxJS 与 Redux 的比较分析

    在当今互联网技术的发展中,前端技术日新月异。RxJS(ReactiveX)和 Redux 是两种在前端领域广泛使用的编程模式。本文将详细比较分析这两种模式的特点、优缺点,及其在实际应用中的使用场景和指...

    1 年前
  • ESLint 无法校验 ES6 中 Map 和 Set 的 forEach 方法

    背景 ESLint 是一种常用的 JavaScript 代码规范检查工具,它能够检测代码质量问题,并给出相应的提示和建议。然而,在使用 ESLint 进行 ES6 代码检查时,可能会遇到一些问题。

    1 年前

相关推荐

    暂无文章