在 JavaScript 中,ArrayBuffer 和 SharedArrayBuffer 是两个重要的数据类型,它们可以用来存储二进制数据。在 ES12 中,这两个数据类型得到了进一步的加强和扩展,本文将详细介绍它们的使用方法。
ArrayBuffer
ArrayBuffer 是一种通用的、固定长度的二进制数据缓冲区,它可以存储任意类型的二进制数据。使用 ArrayBuffer 可以避免在存储和传输二进制数据时进行类型转换的开销,从而提高性能。
创建 ArrayBuffer
创建 ArrayBuffer 的方法很简单,只需要指定缓冲区的长度即可:
const buffer = new ArrayBuffer(8);
上述代码创建了一个长度为 8 字节的 ArrayBuffer。
操作 ArrayBuffer
ArrayBuffer 中的数据是以字节为单位存储的,因此要操作 ArrayBuffer 中的数据需要使用 TypedArray 或 DataView。
TypedArray
TypedArray 是一组类型化数组,它们可以视为 ArrayBuffer 的视图,用来读取和写入 ArrayBuffer 中的数据。常见的 TypedArray 有:
- Int8Array
- Uint8Array
- Int16Array
- Uint16Array
- Int32Array
- Uint32Array
- Float32Array
- Float64Array
以 Int8Array 为例,创建一个长度为 8 字节的 ArrayBuffer,并使用 Int8Array 读写数据:
-- -------------------- ---- ------- ----- ------ - --- --------------- ----- --------- - --- ------------------ -- ------- -------------------------- -- - -- ------- ------------ - ---- -- ------- -------------------------- -- ---
上述代码中,首先创建了一个长度为 8 字节的 ArrayBuffer,然后使用 Int8Array 创建了一个视图,可以通过索引读取和写入数据。
DataView
DataView 是一种通用的数据视图,可以用来读取和写入 ArrayBuffer 中的数据。相比 TypedArray,DataView 的灵活性更高,但性能稍差。
以 DataView 为例,创建一个长度为 8 字节的 ArrayBuffer,并使用 DataView 读写数据:
-- -------------------- ---- ------- ----- ------ - --- --------------- ----- -------- - --- ----------------- -- ------- --------------------------------- -- - -- ------- ------------------- ----- -- ------- --------------------------------- -- ---
上述代码中,首先创建了一个长度为 8 字节的 ArrayBuffer,然后使用 DataView 创建了一个视图,可以通过方法读取和写入数据。
ArrayBuffer 与字符串的转换
ArrayBuffer 与字符串之间的转换是非常常见的操作,可以使用 TextEncoder 和 TextDecoder 完成转换。
以 TextEncoder 为例,将字符串转换为 ArrayBuffer:
const textEncoder = new TextEncoder(); const buffer = textEncoder.encode('hello world').buffer;
上述代码中,首先创建了一个 TextEncoder 实例,然后使用 encode 方法将字符串转换为 Uint8Array,最后通过 buffer 属性获取 ArrayBuffer。
以 TextDecoder 为例,将 ArrayBuffer 转换为字符串:
const textDecoder = new TextDecoder(); const str = textDecoder.decode(buffer); console.log(str); // 'hello world'
上述代码中,首先创建了一个 TextDecoder 实例,然后使用 decode 方法将 ArrayBuffer 转换为字符串。
SharedArrayBuffer
SharedArrayBuffer 是一种多线程共享的 ArrayBuffer,它可以让不同的线程访问同一段内存,从而实现高效的并发编程。
创建 SharedArrayBuffer
创建 SharedArrayBuffer 的方法与创建 ArrayBuffer 类似,只需要指定缓冲区的长度即可:
const buffer = new SharedArrayBuffer(8);
上述代码创建了一个长度为 8 字节的 SharedArrayBuffer。
操作 SharedArrayBuffer
SharedArrayBuffer 中的数据也是以字节为单位存储的,同样需要使用 TypedArray 或 DataView 进行操作。
Atomics
Atomics 是一个全局对象,提供了一组原子操作,可以保证多线程访问 SharedArrayBuffer 时的原子性,避免竞争条件。
常见的原子操作有:
- add
- sub
- and
- or
- xor
- compareExchange
- wait
- wake
以 add 为例,创建一个长度为 8 字节的 SharedArrayBuffer,并使用 add 方法进行原子操作:
const buffer = new SharedArrayBuffer(8); const int32Array = new Int32Array(buffer); // 在索引为 0 的位置上原子地加上 10 Atomics.add(int32Array, 0, 10); // 读取索引为 0 的位置上的值 console.log(int32Array[0]); // 10
上述代码中,首先创建了一个长度为 8 字节的 SharedArrayBuffer,然后使用 Int32Array 创建了一个视图。接着使用 Atomics.add 方法在索引为 0 的位置上原子地加上 10,最后通过索引读取该位置上的值。
Worker
Worker 是一种 Web Worker,可以在后台线程中执行 JavaScript 代码。在 Worker 中可以访问 SharedArrayBuffer,从而实现多线程共享内存。
以创建一个 Worker 为例,让 Worker 访问 SharedArrayBuffer 并进行原子操作:
-- -------------------- ---- ------- -- -------- ----- ------ - --- --------------------- ----- ---------- - --- ------------------- -- ---- - --------- -- ----------------------- -- ---- -- ---- ------ ----- ------ - --- -------------------- -- - ------ ---- --------------------------- -- ---- ------ --- ---------------- - ------- -- - ------------------------ --
-- -------------------- ---- ------- -- --------- --------- - ------- -- - ----- ------ - ----------- ----- ---------- - --- ------------------- -- ---- - --------- -- ----------------------- -- ---- -- -------- --------------------------- --
上述代码中,首先在主线程中创建了一个长度为 8 字节的 SharedArrayBuffer,并使用 Atomics.add 方法在索引为 0 的位置上原子地加上 10。接着创建了一个 Worker,并向 Worker 发送了 SharedArrayBuffer。Worker 中接收到 SharedArrayBuffer 后,也使用 Atomics.add 方法在索引为 0 的位置上原子地加上 20,并将结果发送回主线程。
总结
本文介绍了 ES12 中的 ArrayBuffer 和 SharedArrayBuffer 的使用方法,包括创建、操作和转换等。其中,SharedArrayBuffer 可以实现多线程共享内存,可以用于提高并发编程的性能。开发者需要注意多线程访问时的竞争条件,使用原子操作保证线程安全。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/65d8446a1886fbafa45eee45