Open pfan123 opened 3 years ago
Blob 与 ArrayBuffer
早期 JS 一直没有比较好的可以直接处理二进制的方法。而 Blob 的存在,允许我们可以通过JS直接操作二进制数据。ArrayBuffer 是 Blob 数据格式的组成部分。
Blob(Binary Large Object) 表示二进制类型的大对象。Blob 的概念在一些数据库中有使用到,如 MYSQL 中的 BLOB 类型就表示二进制数据的容器。在 JavaScript 中 Blob 类型的对象表示不可变的类似文件对象的原始数据,会存储在内存中。
File 接口基于 Blob ,继承了 Blob 的功能并将其扩展使其支持用户系统上的文件。
Blob 由一个可选的字符串 type (通常是 MIME 类型)和 blobParts 组成:
const blob = new Blob(['我是Blob'],{type: 'text/html'});
Blob 对象含有两个属性:size 和 type。其中 size 属性用于表示数据的大小(以字节为 单位), type 是 MIME 类型的字符串。
blob.size //Blob大小(以字节为单位) blob.type //Blob的MIME类型,如果是未知,则是“ ”(空字符串)
Blob URL/Object URL 是一种伪协议,允许 Blob 和 File 对象用作图像,下载二进制数据链接等URL源。在浏览器中,我们使用 URL.createObjectURL 方法来创建 Blob URL,该方法接收一个 Blob 对象,并为其创建一个唯一的 URL,其形式为 blob:<origin>/<uuid> ,如下:
URL.createObjectURL
blob:<origin>/<uuid>
blob:https://example.org/40a5fb5a-d56d-4a33-b4e2-0acf6a8e5f641
浏览器内部为每个通过 URL.createObjectURL 生成的 URL 存储了一个 URL → Blob 映射。生成的 URL 仅在当前文档打开的状态下才有效。
URL → Blob
const blobURL = URL.createObjectURL(blob);
Blob URL 实际上会存在有副作用。存储的 URL → Blob 映射,会导致驻留在内存中的 Blob 对象,无法被浏览器释放。在文档卸载时会映射自动清除,Blob 对象也会随之被释放。但如果应用程序寿命很⻓,就会出现长期占用内存的情况。
Blob URL
针对这个问题,可以调用 URL.revokeObjectURL(url) 方法,从内部映射中删除引用,从而允许删除 Blob(如果没有其他引用),并释放内存。
URL.revokeObjectURL(url)
window.URL.revokeObjectURL(blobURL);
function upload(blobOrFile) { const xhr = new XMLHttpRequest(); xhr.open('POST', '/server', true); xhr.onload = function(e) { ... }; xhr.send(blobOrFile); } document.querySelector('input[type="file"]').addEventListener('change', function(e) { const blob = this.files[0]; const BYTES_PER_CHUNK = 1024 * 1024; // 1MB chunk sizes. const SIZE = blob.size; let start = 0; let end = BYTES_PER_CHUNK; while(start < SIZE) { upload(blob.slice(start, end)); start = end; end = start + BYTES_PER_CHUNK; } }, false)
const video = document.getElementById('video'); const obj_url = window.URL.createObjectURL(blob); // ArrayBuffer Blob video.src = obj_url; video.play() window.URL.revokeObjectURL(obj_url);
在"被污染"的画布中调用以下方法将会抛出安全错误:
在 的上下文上调用getImageData()
在 上调用 toBlob()
在 上调用 toDataURL()
结合 canvas 绘图,使用 createObjectURL(blob) 输出页面,实现移动端长按保存、转发,示例
Web Worker 串行加载优化
使用 Blob、URL.createObjectURL 优化后,减少一次请求:
service worker 脚本的 URL, 不支持 Blob/String URL,Create service worker from Blob/String URL。
const workerContent = `self.addEventListener('message', function (evt) { const num1 = evt.data.num1; const num2 = evt.data.num2; const result = num1 + num2; self.postMessage({result: result}); }, false)`; const workerBlob = new Blob([workerContent], { type:'text/javascript' }); const workerUrl = window.URL.createObjectURL(workerBlob); const worker = new Worker(workerUrl); window.URL.revokeObjectURL(workerUrl); worker.addEventListener('message', function(evt) { console.log(`[main] result is: ${evt.data.result}.`); }, false); worker.postMessage({num1: 20, num2: 10});
ES2015 推出之后,JavaScript 开始支持在原始二进制缓冲区中读取和写入数据,这个缓冲区被称为 ArrayBuffer 。
ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。它是一个字节数组,通常在其他语言中称为“byte array”。
我们不能直接操作 ArrayBuffer 的内容,而是要通过 TypedArray 对象或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。
ArrayBuffer 目前似乎应用的场景不多,但了解它,可以让我们理解 JavaScript 如何直接操作字节模块。
可尝试利用 ArrayBuffer 与 WebAssembly 进行更高效率的交互
TypedArray 允许程序以统一的类型数组的形式访问缓冲区,例如 Int8Array、Int16Array 或 Float32Array 。
const buffer = new ArrayBuffer(32); const array = new Int16Array(buffer); for (let i = 0; i < array.length; i++) { array[i] = i * i; }
DataView 允许更细粒度的数据访问。 我们可以通过为每种值类型提供专门的 getter 和 setter 来选择从缓冲区读取和写入的值的类型,这使得 DateView 可用于序列化数据结构。
const buffer = new ArrayBuffer(32); const view = new DataView(buffer); const person = { age: 42, height: 1.76 }; view.setUint8(0, person.age); view.setFloat64(1, person.height); console.log(view.getUint8(0)); // 输出: 42 console.log(view.getFloat64(1)); // 输出: 1.76
Buffer是 Node.JS 中用于操作 ArrayBuffer 的视图,是 TypedArray 的一种。
Buffer
ArrayBuffer
TypedArray
Buffer 类是 JavaScript 的 Uint8Array 类的子类,且继承时带上了涵盖额外用例的方法。 只要支持 Buffer 的地方,Node.js API 都可以接受普通的 Uint8Array。
Uint8Array
创建一个Buffer 对象时,JavaScript会根据请求内存的大小,分成两种方式来分配内存。
Blob 对象与 ArrayBuffer 对象拥有各自的特点,它们之间的区别如下:
Blob 对象是不可变的,而 ArrayBuffer 是可以通过 TypedArrays 或 DataView 来操作。
ArrayBuffer 是存在 V8 内存中的,可以直接操作。而 Blob 可以位于磁盘、高速缓存内存和其他不可用的位置。
Blob 与 ArrayBuffer 对象之间是可以相互转化的:
document.querySelector('input[type="file"]').addEventListener('change', function(e) { const blob = this.files[0]; const fileType = blob.slice(0, 4); const reader = new FileReader(); reader.readAsArrayBuffer(fileType); reader.onload = function (e) { let buffer = reader.result; let view = new DataView(buffer); let magic = view.getUint32(0, false); switch(magic) { case 0x89504E47: file.verified_type = 'image/png'; break; case 0x47494638: file.verified_type = 'image/gif'; break; case 0x25504446: file.verified_type = 'application/pdf'; break; case 0x504b0304: file.verified_type = 'application/zip'; break; } }; }, false)
使用 Blob 构造函数,如 new Blob([new Uint8Array(data]),可以把 ArrayBuffer 对 象转换为 Blob 对象。
AJAX 场景下,我们也可能会用到 Blob 或 ArrayBuffer 对象。
function GET(url, callback) { let xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.responseType = 'arraybuffer'; // or xhr.responseType = "blob"; xhr.send(); xhr.onload = function(e) { if (xhr.status != 200) { alert("Unexpected status code " + xhr.status + " for " + url); return false; } callback(new Uint8Array(xhr.response)); // or new Blob([xhr.response]); }; }
ArrayBuffer 和 Buffer 有何区别?
Node.js 中的缓冲区(Buffer)究竟是什么?
Blob 与 ArrayBuffer
早期 JS 一直没有比较好的可以直接处理二进制的方法。而 Blob 的存在,允许我们可以通过JS直接操作二进制数据。ArrayBuffer 是 Blob 数据格式的组成部分。
Blob
Blob(Binary Large Object) 表示二进制类型的大对象。Blob 的概念在一些数据库中有使用到,如 MYSQL 中的 BLOB 类型就表示二进制数据的容器。在 JavaScript 中 Blob 类型的对象表示不可变的类似文件对象的原始数据,会存储在内存中。
File 接口基于 Blob ,继承了 Blob 的功能并将其扩展使其支持用户系统上的文件。
Blob 由一个可选的字符串 type (通常是 MIME 类型)和 blobParts 组成:
构造 Blob
Blob 属性
Blob 对象含有两个属性:size 和 type。其中 size 属性用于表示数据的大小(以字节为 单位), type 是 MIME 类型的字符串。
Blob URL/Object URL
Blob URL/Object URL 是一种伪协议,允许 Blob 和 File 对象用作图像,下载二进制数据链接等URL源。在浏览器中,我们使用
URL.createObjectURL
方法来创建 Blob URL,该方法接收一个 Blob 对象,并为其创建一个唯一的 URL,其形式为blob:<origin>/<uuid>
,如下:浏览器内部为每个通过
URL.createObjectURL
生成的 URL 存储了一个URL → Blob
映射。生成的 URL 仅在当前文档打开的状态下才有效。Blob URL
实际上会存在有副作用。存储的URL → Blob
映射,会导致驻留在内存中的 Blob 对象,无法被浏览器释放。在文档卸载时会映射自动清除,Blob 对象也会随之被释放。但如果应用程序寿命很⻓,就会出现长期占用内存的情况。针对这个问题,可以调用
URL.revokeObjectURL(url)
方法,从内部映射中删除引用,从而允许删除 Blob(如果没有其他引用),并释放内存。Blob 常见使用场景
结合 canvas 绘图,使用 createObjectURL(blob) 输出页面,实现移动端长按保存、转发,示例
Web Worker 串行加载优化
使用 Blob、URL.createObjectURL 优化后,减少一次请求:
ArrayBuffer
ES2015 推出之后,JavaScript 开始支持在原始二进制缓冲区中读取和写入数据,这个缓冲区被称为 ArrayBuffer 。
ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。它是一个字节数组,通常在其他语言中称为“byte array”。
我们不能直接操作 ArrayBuffer 的内容,而是要通过 TypedArray 对象或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。
ArrayBuffer 目前似乎应用的场景不多,但了解它,可以让我们理解 JavaScript 如何直接操作字节模块。
TypedArray 操作 ArrayBuffer
TypedArray 允许程序以统一的类型数组的形式访问缓冲区,例如 Int8Array、Int16Array 或 Float32Array 。
DataView 操作 ArrayBuffer
DataView 允许更细粒度的数据访问。 我们可以通过为每种值类型提供专门的 getter 和 setter 来选择从缓冲区读取和写入的值的类型,这使得 DateView 可用于序列化数据结构。
Buffer
Buffer
是 Node.JS 中用于操作ArrayBuffer
的视图,是TypedArray
的一种。Buffer
类是 JavaScript 的Uint8Array
类的子类,且继承时带上了涵盖额外用例的方法。 只要支持Buffer
的地方,Node.js API 都可以接受普通的Uint8Array
。创建一个
Buffer
对象时,JavaScript会根据请求内存的大小,分成两种方式来分配内存。ArrayBuffer
对象Blob 对象与 ArrayBuffer 对象对比
Blob 对象与 ArrayBuffer 对象拥有各自的特点,它们之间的区别如下:
Blob 对象是不可变的,而 ArrayBuffer 是可以通过 TypedArrays 或 DataView 来操作。
ArrayBuffer 是存在 V8 内存中的,可以直接操作。而 Blob 可以位于磁盘、高速缓存内存和其他不可用的位置。
Blob 与 ArrayBuffer 对象之间是可以相互转化的:
使用 Blob 构造函数,如 new Blob([new Uint8Array(data]),可以把 ArrayBuffer 对 象转换为 Blob 对象。
AJAX 场景下,我们也可能会用到 Blob 或 ArrayBuffer 对象。
Other Resources
ArrayBuffer 和 Buffer 有何区别?
Node.js 中的缓冲区(Buffer)究竟是什么?