ArrayBuffer 与 Blob
ArrayBuffer 对象
简介
ArrayBuffer 对象表示一段二进制数据,用来模拟内存里面的数据。通过这个对象,JavaScript 可以读写二进制数据,可以看作内存数据的表达。这个对象是 ES6 才写入标准的。
浏览器原生提供ArrayBuffer()构造函数,用来生成实例。它接受一个整数作为参数,表示这段二进制数据占用多少个字节。
const buffer = new ArrayBuffer(8);
上面代码中,实例对象buffer占用8个字节。
ArrayBuffer 对象有实例属性byteLength,表示当前实例占用的内存长度(单位字节)。
ArrayBuffer 对象有实例方法slice(),用来复制一部分内存。它接受两个整数参数,分别表示复制的开始位置(从0开始)和结束位置(复制时不包括结束位置),如果省略第二个参数,则表示一直复制到结束。
var buf1 = new ArrayBuffer(8);var buf2 = buf1.slice(0);
上面代码表示复制原来的实例。
TypedArray
TypedArray 对象代表了格式化的二进制数据,它们是 ArrayBuffer 的视图。由于 ArrayBuffer 本身只是一段内存,无法直接读写其中的内容。TypedArray 扮演着“翻译官”的角色,它将 ArrayBuffer 中的原始二进制数据转换成特定类型(如 8 位整数、32 位浮点数等)的数组,可以方便地进行操作和查看数据。
类型
JavaScript 提供了多种 TypedArray,每种都对应一种特定的数据类型,例如:
- Int8Array:8 位有符号整数
- Uint8Array:8 位无符号整数
- Int16Array:16 位有符号整数
- Uint16Array:16 位无符号整数
- Int32Array:32 位有符号整数
- Uint32Array:32 位无符号整数
- Float32Array:32 位浮点数
- Float64Array:64 位浮点数
操作
创建一个 TypedArray 实例时,它会自动在内部创建一个 ArrayBuffer。例如:
// 创建一个包含 16 个 32 位整数的 TypedArray
const int32View = new Int32Array(16);也可以在一个已有的 ArrayBuffer 之上创建一个 TypedArray,可以用不同的视角去查看同一块内存。
// 创建一个 8 字节的 ArrayBuffer
const buffer = new ArrayBuffer(8);
// 创建一个 Uint8Array 视图,将 buffer 看作 8 个 8 位无符号整数
const uint8View = new Uint8Array(buffer);
console.log(uint8View.length); // 8
// 创建一个 Uint16Array 视图,将 buffer 看作 4 个 16 位无符号整数
const uint16View = new Uint16Array(buffer);
console.log(uint16View.length); // 4像操作普通数组一样来操作 TypedArray,包括读写值、遍历等。
// 创建一个 Int8Array,长度为 4
const int8View = new Int8Array(4);
// 写入数据
int8View[0] = 10;
int8View[1] = -20;
// 读取数据
console.log(int8View[0]); // 10
console.log(int8View[1]); // -20
// 遍历
for (const value of int8View) {
console.log(value);
}当通过 TypedArray 写入数据时,如果数值超出其类型所能表示的范围,会自动进行截断处理。例如,一个 Int8Array 只能存储 -128 到 127 之间的整数,如果写入 256,它会被截断为 0。
应用场景
- 处理二进制数据:在处理文件、图像、音频或网络数据时,TypedArray 是必不可少的。它能够高效地读取和写入底层的二进制流。
- WebGL 和 WebGPU:在图形编程中,TypedArray 用于存储顶点、颜色等大量数据,并将其传递给 GPU。
- 性能优化:当处理大型数值数据集时,TypedArray 的性能通常优于普通 JavaScript 数组。
- 共享内存:在多线程(如 Web Workers)环境中,TypedArray 可以与 SharedArrayBuffer 配合,实现不同线程间高效的数据共享。
Blob 对象
简介
Blob 对象表示一个不可变、原始数据的类文件对象。它通常用来处理文件,它的名字是 Binary Large Object(二进制大型对象)的缩写。它与 ArrayBuffer 的区别在于,它用于操作二进制文件,而 ArrayBuffer 用于操作内存。
浏览器原生提供Blob()构造函数,用来生成实例对象。
new Blob(array,options)
Blob构造函数接受两个参数。第一个参数是数组,成员是字符串或二进制对象,表示新生成的Blob实例对象的内容;第二个参数是可选的配置对象,目前只有一个属性type,表示数据的 MIME 类型,默认是空字符串。
实例属性和实例方法
Blob具有两个实例属性size和type,分别返回数据的大小和类型。
var htmlFragment = ['<a id="a"><b id="b">hey!</b></a>'];
var myBlob = new Blob(htmlFragment, {type : 'text/html'})
myBlob.size // 32
myBlob.type // "text/html"实例方法:
- arrayBuffer() 返回一个
Promise,会兑现一个包含 blob 二进制数据内容的ArrayBuffer - bytes() 返回一个
Promise,会兑现为一个包含 blob 内容的字节数组的Uint8Array - slice() 创建并返回一个新的 Blob 对象,该对象包含调用它的 blob 的子集中的数据。
- text 返回
Promise,兑现一个包含 blob 内容的 UTF-8 格式的字符串。 - stream 返回一个
ReadableStream对象,读取它将返回包含在Blob中的数据。
生成 URL
浏览器允许使用URL.createObjectURL()方法,针对 Blob 对象生成一个临时 URL,以便于某些 API 使用。这个 URL 以blob://开头,表明对应一个 Blob 对象,协议头后面是一个识别符,用来唯一对应内存里面的 Blob 对象。这一点与data://URL(URL 包含实际数据)和file://URL(本地文件系统里面的文件)都不一样。
File drag and drop HTML 拖放接口使得 web 应用能够在网页中拖放文件,下面的案例用了拖放接口。
<div style="background-color: grey; padding: 20px; text-align: center;" ondrop="dropHandler(event);"
ondragover="dragOverHandler(event);">
<p>Drag one or more files to this Drop Zone ...</p>
</div>
<script>
function dragOverHandler(ev) {
event.preventDefault()
}
function dropHandler(ev) {
console.log("File(s) dropped", ev.dataTransfer.items);
// 阻止浏览器默认行为 (打开文件)
ev.preventDefault();
if (ev.dataTransfer.items) {
// 使用 DataTransfer.items
for (var i = 0; i < ev.dataTransfer.items.length; i++) {
// If dropped items aren't files, reject them
if (ev.dataTransfer.items[i].kind === "file") {
var file = ev.dataTransfer.items[i].getAsFile();
console.log("111... file[" + i + "].name = " + file.name);
var img = document.createElement('img');
img.src = URL.createObjectURL(file);
img.onload = function () {
this.width = 100;
document.body.appendChild(this);
URL.revokeObjectURL(this.src);
}
}
}
} else {
// 也可以使用 DataTransfe.files
for (var i = 0; i < ev.dataTransfer.files.length; i++) {
console.log(
"222... file[" + i + "].name = " + ev.dataTransfer.files[i].name,
);
}
}
}
</script>上面代码通过为拖放的图片文件生成一个 URL,产生它们的缩略图,从而使得用户可以预览选择的文件。
浏览器处理 Blob URL 就跟普通的 URL 一样,如果 Blob 对象不存在,返回404状态码;如果跨域请求,返回403状态码。Blob URL 只对 GET 请求有效,如果请求成功,返回200状态码。由于 Blob URL 就是普通 URL,因此可以下载。
文件操作
见下一节