在前端开发过程中,很多时候需要处理二进制数据。ES12 中引入了类型化数组和 ArrayBuffer,可以方便的处理和操作二进制数据。本文将详细介绍类型化数组和 ArrayBuffer 的相关知识和使用方法。
ArrayBuffer
ArrayBuffer 是一个固定长度的二进制数据缓冲区,其长度在创建时已经确定。可以使用以下方式创建 ArrayBuffer:
let buffer = new ArrayBuffer(length);
其中,length 表示缓冲区的长度,以字节为单位。例如,创建一个长度为 16 字节的 ArrayBuffer:
let buffer = new ArrayBuffer(16);
使用.slice()方法可以对 ArrayBuffer 进行切片,不同的切片共享同一块内存。例如,切片一个长度为 16 字节的 ArrayBuffer:
let buffer = new ArrayBuffer(16); let slice1 = buffer.slice(0, 8); // 切片 0-7 字节 let slice2 = buffer.slice(8); // 切片 8-15 字节
类型化数组
类型化数组是一种类似于数组的对象,可以用来表示和操作基于 ArrayBuffer 的二进制数据。类型化数组有以下几种类型:
| 类型 | 含义 | 字节大小 | 取值范围 |
|---|---|---|---|
| Int8Array | 带符号 8 位整数 | 1 | -128 ~ 127 |
| Uint8Array | 无符号 8 位整数 | 1 | 0 ~ 255 |
| Uint8ClampedArray | 无符号 8 位整数(截断) | 1 | 0 ~ 255 |
| Int16Array | 带符号 16 位整数 | 2 | -32768 ~ 32767 |
| Uint16Array | 无符号 16 位整数 | 2 | 0 ~ 65535 |
| Int32Array | 带符号 32 位整数 | 4 | -2^31 ~ 2^31-1 |
| Uint32Array | 无符号 32 位整数 | 4 | 0 ~ 2^32-1 |
| Float32Array | 单精度浮点数 | 4 | IEEE754 规范 |
| Float64Array | 双精度浮点数 | 8 | IEEE754 规范 |
| BigInt64Array | 带符号 64 位整数 | 8 | -2^63 ~ 2^63-1 |
| BigUint64Array | 无符号 64 位整数 | 8 | 0 ~ 2^64-1 |
可以使用以下方式创建类型化数组:
let array = new TypeArray(buffer, offset, length);
其中,TypeArray 表示类型化数组类型,buffer 是一个 ArrayBuffer 对象,offset 表示数组在缓冲区中的偏移量,length 表示数组的长度。
例如,创建一个长度为 8 的 Int8Array:
let buffer = new ArrayBuffer(16); let array = new Int8Array(buffer, 0, 8);
操作类型化数组
通过类型化数组的索引访问元素的方式和普通数组一样。例如:
let array = new Int8Array(8); array[0] = 10; array[1] = 20; console.log(array[0]); // 10 console.log(array[1]); // 20
类型化数组还支持 map()、reduce()、forEach() 等方法和普通数组一样。
视图(View)
类型化数组之间也可以相互转换,使用视图(View)的方式实现。视图是一种连续访问二进制数据的方式,可以用来访问同一个 ArrayBuffer。
例如,将一个 Int8Array 转换为 Int16Array:
let buffer = new ArrayBuffer(8); let array1 = new Int8Array(buffer); // 长度为 8 个字节的 Int8Array let array2 = new Int16Array(buffer); // 长度为 4 个字节的 Int16Array
示例代码
以下是一个使用类型化数组和 ArrayBuffer 处理二进制数据的示例代码,该代码实现了将一个字符串转换为 UTF8 编码的二进制数据,然后将该二进制数据转换回字符串:
// www.javascriptcn.com code example
let str = "hello world";
// 转换为 UTF8 编码的二进制数据
let buffer = new ArrayBuffer(str.length * 3);
let array = new Uint8Array(buffer);
let index = 0;
for (let i = 0; i < str.length; i++) {
let code = str.charCodeAt(i);
if (code <= 0x7f) {
array[index++] = code;
} else if (code <= 0x7ff) {
array[index++] = (code >>> 6) | 0xc0;
array[index++] = (code & 0x3f) | 0x80;
} else {
array[index++] = (code >>> 12) | 0xe0;
array[index++] = ((code >>> 6) & 0x3f) | 0x80;
array[index++] = (code & 0x3f) | 0x80;
}
}
// 将二进制数据转换回字符串
let result = "";
let length = index;
for (let i = 0; i < length; i++) {
let code = array[i];
if (code <= 0x7f) {
result += String.fromCharCode(code);
} else if (code <= 0xdf && i + 1 < length) {
result += String.fromCharCode(((code & 0x1f) << 6) | (array[++i] & 0x3f));
} else if (code <= 0xef && i + 2 < length) {
result += String.fromCharCode(
((code & 0x0f) << 12) |
((array[++i] & 0x3f) << 6) |
(array[++i] & 0x3f)
);
} else {
result += String.fromCharCode(
((code & 0x07) << 18) |
((array[++i] & 0x3f) << 12) |
((array[++i] & 0x3f) << 6) |
(array[++i] & 0x3f)
);
}
}
console.log(result);结束语
类型化数组和 ArrayBuffer 可以方便的操作和处理二进制数据,在前端开发中具有广泛的应用场景。本文介绍了类型化数组和 ArrayBuffer 的相关知识和使用方法,希望能够对读者有所帮助。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d682fca941bf7134c4c6a3