![[二进制数据.excalidraw]]
ArrayBufferArrayBuffer 是用来表示通用的原始二进制数据缓冲区,本质是一个字节数组
const buffer = new ArrayBuffer(16) // 创建一个长度为 16 Byte 的 buffer
console.log(buffer.byteLength) // 16
注意:创建后长度固定,不可调整
它会分配一个 16 字节的连续内存空间,并用 0 进行预填充
ArrayBuffer 不是 Array
ArrayBuffer 是对固定长度的连续内存空间的引用,不同与 Array:
buffer[index]Array.prototype 上 push、pop 等方法ArrayBuffer 本身不能直接读写,需要借助数据视图:
TypedArray 视图:如 Uint8Array、Float32ArrayDataView 视图:更灵活,支持任意偏移和字节长度ArrayBuffer 是一个内存区域,它里面存储了什么无从判断,只是一个原始的字节序列。想要操作 ArrayBuffer,需要使用“视图”对象。视图对象本身并不存储任何东西,它是一副“眼镜”,透过它来解释存储在 ArrayBuffer 中的字节
![[Pasted image 20240817183421.png]]
| 类型化数组 | 每个元素所占字节数 | 描述(C 语言中的数据类型) |
|---|---|---|
Int8Array |
1 | 8 位整型数(signed char) |
UInt8Array |
1 | 8 位无符号整型数(unsigned char) |
Uint8ClampedArray |
1 | 8 位无符号整型数,溢出时有特殊处理 |
Int16Array |
2 | 16 位整型数(signed short) |
UInt16Array |
2 | 16 位无符号整型数(unsigned short) |
Int32Array |
4 | 32 位整型数(signed int) |
UInt32Array |
4 | 32 位无符号整型数(unsigned int) |
BigInt64Array |
8 | 64 位整型数(signed long / long long) |
BigUint64Array |
8 | 64 位整型数(unsigned long / long long) |
Float32Array |
4 | 单精度 32 位浮点数(float) |
Float64Array |
8 | 双精度 64 位浮点数(double) |
TypedArray 的说明
没有名为 TypedArray 的构造器,它只是表示 ArrayBuffer 上的视图之一的通用总称术语
当你看到 new TypedArray 之类的内容时,它表示 new Int8Array、new Uint8Array 及其他中之一
new TypedArray(buffer, byteOffset?, length?)
buffer:ArrayBuffer 或 SharedArrayBufferbyteOffset:视图的起始字节位置(即:跳过几个字节长度的数据),默认为 0length:视图的字节长度,默认至 buffer 的末尾new TypedArray(object)
Array,或类数组对象,或可迭代对象,则会创建一个相同长度的类型化数组,并复制其内容new Uint8Array([0, 1, 2, 3])new TypedArray(typedArray)
ArrayBuffer)new TypedArray(length?)
length 乘以单个 TypedArray.BYTES_PER_ELEMENT 中的字节数可以直接创建一个 TypedArray,而无需提及 ArrayBuffer。但是,视图离不开底层的 ArrayBuffer,因此,除第一种情况(已提供 ArrayBuffer)外,其他所有情况都会自动创建底层 ArrayBuffer
如要访问底层的 ArrayBuffer,在 TypedArray 中有如下的属性:
buffer:引用底层 ArrayBufferbyteLength:底层 ArrayBuffer 的长度(即:数据占用字节数)byteOffset:当前视图相对底层 ArrayBuffer 的偏移值其他属性:
length:包含多少元素BYTES_PER_ELEMENT:每个元素占用的字节数TypedArray 具有和 Array 相同的方法设计,可以设置获取元素(arr[i]、set、get)、查找(indexOf、lastIndexOf)、填充(fill)、切片(slice)、反转(reverse)、排序(sort)、拼接字符串(join)、遍历(forEach、map、find、reduce )等
但没有 push、pop、shift、unshift、splice、concat 等会改变数组长度的方法
还有两种 Array 没有的方法:
arr.set(fromArr, offset?):从 offset(默认为 0)开始,将 fromArr 中的所有元素复制到 arrarr.subarray(begin?, end?):创建一个从 begin 到 end(包头不包尾)相同类型的新视图。这类似于 slice 方法,但不复制任何内容(只是创建一个新视图,以对给定片段的数据进行操作)如果尝试将越界值写入类型化数组,多余的高位数据将会被忽略
如尝试将 256 放入 Uint8Array,则超出的最高位的 1 会被忽略,因此结果是 0:
![[Pasted image 20240817175322.png]]
Uint8ClampedArray 在这方面比较特殊,它的表现不太一样。对于大于 255 的任何数字,它将保存为 255,对于任何负数,它将保存为 0。此行为对于图像或颜色处理很有用
类型化数组限制了数据每个元素的字节大小,而 DataView 是在 ArrayBuffer 上的一种超灵活的“未类型化”视图,它允许以任何格式访问任何偏移量(offset)的数据
i 个元素是 arr[i]DataView:可以使用 .getUint8(offset) 或 .getUint16(offset) 之类的方法访问数据。在调用方法时选择格式,而不是在构造的时候new DataView(buffer, byteOffset?, byteLength?)
buffer:ArrayBuffer 或 SharedArrayBufferbyteOffset:视图的起始字节位置(即:跳过几个字节长度的数据),默认为 0length:视图的字节长度,默认至 buffer 的末尾DataView 与类型化数组不同,只有这一个构造器,即 DataView 不会自行创建缓冲区,需要事先准备好
buffer:引用底层 ArrayBufferbyteLength:底层 ArrayBuffer 的长度(即:数据占用字节数)byteOffset:当前视图相对底层 ArrayBuffer 的偏移值没有与 Array 或 TypedArray [[#^1|相类型的方法]],只有对不同偏移量读写的方法:
getXxx(byteOffset, littleEndian?):获取指定字节偏移量处的数据setXxx(byteOffset, value, littleEndian?):设置指定字节偏移量处的数据
Xxx:Int8|Uint8|Int16|Uint16|Int32|Uint32|BigInt64|BigUint64|Float32|Float64 之一littleEndian:采用何种[[#字节序|字节序]]
false 或者未指定(undefined):大端序true:小端序字节序或字节顺序描述了计算机如何组织构成数字的字节
例如,用不同字节序存储数字 0x12345678:
0x78 0x56 0x34 0x120x12 0x34 0x56 0x780x34 0x12 0x78 0x56Blob 全称 Binary Large Object,表示一个不可变的原始数据块,支持文本和二进制数据
特点:
ArrayBuffer、TypedArray 等创建方式:
const blob = new Blob(
["Hello World"],
{ type: "text/plain" }
);
切片操作:
const slicedBlob = blob.slice(0, 5, "text/plain");
| 功能 | 说明 |
|---|---|
| 分片上传 | .slice(start, end) 方法可用于大文件切片上传 |
| 本地预览 | canvas.toBlob() 导出图像,配合 URL.createObjectURL 预览 |
| 文件下载 | 使用 a 标签 + createObjectURL 实现无刷新下载 |
| 缓存资源 | Service Worker 中缓存 Blob 数据提升性能 |
| 处理用户上传 | 结合 FileReader 和 File API 操作用户文件 |
[[004.浏览器离线存储#File API|File API]]
File 对象继承自 Blob,额外包含:文件名 name ,最后修改时间 lastModified ,可以理解为:带有元数据的 Blob
创建方式:
const file = new File(
["Hello World"],
"example.txt",
{ type: "text/plain" }
);
一般通过用户上传的文件获取
示例:
// <input type="file">
const input = document.getElementById("input");
input.onchange = (event) => {
const files = event.target.files;
console.log("Files:", files); // FileList
};
FileReader 是一个用于异步读取 Blob 或 File 内容的接口
| 方法 | 说明 |
|---|---|
readAsArrayBuffer() |
读取为 ArrayBuffer,适合二进制 |
readAsText() |
读取为字符串 |
readAsDataURL() |
读取为 Base64 编码 |
readyState: 当前读取状态result: 读取完成后的数据(异步获取)let blob = new Blob(["Hello World!"], { type: "text/plain" });
blob = blob.slice(0, 5, "text/plain");
const fileReader = new FileReader();
fileReader.readAsText(blob);
fileReader.onload = function() {
console.log(fileReader.result); // Hello
};
ObjectURL 用于为 Blob 或 File 对象生成一个临时 URL,可直接在 <img>、<a>、iframe 等 标签中使用
const input = document.getElementById("input");
const image = document.getElementById("image");
input.onchange = (event) => {
const file = event.target.files[0];
const url = URL.createObjectURL(file);
image.src = url;
};