[TOC]
>[info]文件、圖片以什么樣的形式傳輸、存儲在某些場合是一個很棘手的問題,這里記錄一些常用的數據類型 / 形式方便以后查閱
# Blob
Blob(binary large object),二進制類文件大對象,是一個可以存儲二進制文件的“容器”,HTML5 中的 Blob 對象除了存放二進制數據外還可以設置這個數據的 MIME 類型。File 接口基于 Blob,繼承了 blob 的功能并將其擴展使其支持用戶系統上的文件。
Blob 構造函數接受兩個參數,第一個參數是一個包含實際數據的數組,第二個參數是數據的 MIME 類型(標識郵件和 http 請求的網絡數據格式)。
```
var blob=new Blob([data],{"type":"text/html"});
```
- Blob.size:放回 blob 對象的數據大小
- Blob.type:返回 blob 對象的 MIME 類型
- Blob.slice():截取指定范圍的數據,形成新的 blob 對象
示例1:圖片選擇與下載
```
<input type="file" value="點我" id="inputImg" onchange="changeHandle(this)">
<img id="image">
let changeHandle = (file) =>{
var reader = new FileReader();
reader.onload = function(evt){
document.getElementById('image').src = evt.target.result;
image = evt.target.result;
}
// 讀Blob為base64
reader.readAsDataURL(file.files[0]);
}
```
示例2:向服務器請求圖片并掛載
```
var xhr = new XMLHttpRequest();
xhr.open("get", "mm1.jpg", true); // 向服務器請求圖片
xhr.responseType = "blob"; // blob 形式
xhr.onload = function() {
if (this.status == 200) {
var blob = this.response; // this.response也就是請求的返回就是Blob對象
var img = document.createElement("img");
img.onload = function(e) {
window.URL.revokeObjectURL(img.src); // 清除釋放
};
img.src = window.URL.createObjectURL(blob); // 使用該 API 可以創建一個 URL 來訪問該圖片
eleAppend.appendChild(img);
}
}
xhr.send();
```
注意 window.URL.createObjectURL() 這個 API,其可以接收 File 對象或 Blob 對象參數生成一個下載 / 加載鏈接(???)
```
axios.get('https://xxxxxx', {responseType: 'blob'})
.then(res => {
let url = URL.createObjectURL(res.data)
let a = document.createElement('a')
a.setAttribute('download', '圖片')
a.href = url
a.click()
})
```
## ArrayBuffer 與 Blob
* Blob 和 ArrayBuffer 都能存儲二進制數據。Blob 相對而言儲存的二進制數據大(如File文件對象)。
* ArrayBuffer 對象表示原始的二進制數據緩沖區,即在內存中分配指定大小的二進制緩沖區(容器),用于存儲各種類型化數組的數據,是最基礎的原始數據容器,無法直接讀取或寫入, 需要通過具體視圖來讀取或寫入,即 TypedArray 對象或 DataView 對象對內存大小進行讀取或寫入;Blob 對象表示一個不可變、原始數據的類文件對象。
可以相互轉換。
Blob => ArrayBuffer
```
let blob = new Blob([1,2,3,4])
let reader = new FileReader();
reader.onload = function(result) {
console.log(result);
}
reader.readAsArrayBuffer(blob);
```
ArrayBuffer => Blob
```
let blob = new Blob([buffer])
```
# 圖片格式
- 無壓縮。無壓縮的圖片格式不對圖片數據進行壓縮處理,能準確地呈現原圖片。BMP 格式就是其中之一。
- 無損壓縮。壓縮算法對圖片的所有的數據進行編碼壓縮,能在保證圖片的質量的同時降低圖片的尺寸。png 是其中的代表。
- 有損壓縮。壓縮算法不會對圖片所有的數據進行編碼壓縮,而是在壓縮的時候,去除了人眼無法識別的圖片細節。因此有損壓縮可以在同等圖片質量的情況下大幅降低圖片的尺寸。其中的代表是 jpg。
|格式 |優點 | 缺點 | 適用場景 |
| :----| :----| :----| :----|
|gif |文件小,支持動畫、透明,無兼容性問題 |只支持 256 種顏色 | 色彩簡單的 logo、icon、動圖|
| jpg(jpeg)| 色彩豐富,文件小|有損壓縮,反復保存圖片質量下降明顯 |色彩豐富的圖片/漸變圖像 |
| png| 無損壓縮,支持透明,簡單圖片尺寸小| 不支持動畫,色彩豐富的圖片| logo/icon/透明圖|
|webp | 文件小,支持有損和無損壓縮,支持動畫、透明|瀏覽器兼容性不好 | 支持 webp 格式的 app 和 webview|
如何做選擇?(Google 圖片格式選擇指南)

# 二進制數組
ArrayBuffer 對象、TypedArray 視圖和 DataView 視圖是 JavaScript 操作二進制數據的一個接口,ES6 將它們納入了 ECMAScript 規格,并且增加了新的方法。它們都以數組的語法處理二進制數據,所以統稱為**二進制數組**。
 為什么要以二進制而不是傳統的文本格式來進行數據通信?文本格式傳遞數據是比較費時的(格式轉換),這個接口的原始設計目的與 WebGL 項目有關,WebGL 即瀏覽器與顯卡之間的通信接口,為了滿足 JavaScript 與顯卡之間大量、實時的數據交換,它們之間的數據通信必須是二進制的。
 二進制數組允許開發者以數組下標的形式直接操作內存,大大增強了 JavaScript 處理二進制數據的能力,其由 3 類對象組成
1. ArrayBuffer 對象:代表內存中的一段二進制數據,可以通過"視圖"進行操作。"視圖"部署了數組接口,這意味著,可以通過數組的方法操作內存
2. TypedArray 視圖:共包括 9 種類型的視圖,如 Int16Array(16位整數)數組視圖、Float32Array(32位浮點數)數組視圖等
3. DataView 視圖:可以自定義復合格式的視圖,比如第一個字節是 Uint8(無符號8位整數)、第二和第三個字節是 Int16(16位整數)
簡而言之:ArrayBuffer 對象代表原始的二進制數據,TypedArray 視圖用于讀 / 寫簡單類型的二進制數據,DataView 視圖用于讀 / 寫復雜類型的二進制數據。
> 二進制數組并不是真正的數組,而是類似數組的對象。很多瀏覽器操作的 API 都用到了二進制數組操作二進制數據,如 File API、XMLHttpRequest、Fetch API、Canvas、WebSocket
## ArrayBuffer 對象
ArrayBuffer 對象代表儲存二進制數據的一段內存,它不能直接讀 / 寫,只能通過視圖(TypedArray 視圖和 DataView 視圖)讀 / 寫,視圖的作用是以指定格式解讀二進制數據
- ArrayBuffer():構造函數,分配一段可以存放數據的連續內存區域,單位為字節
```
var buf = new ArrayBuffer(32)
// 生成一段 32 字節的內存區域,每個字節的值默認為 0
```
- ArrayBuffer.prototype.byteLength:返回所分配的內存區域的字節長度
```
var buffer = new ArrayBuffer(32)
buffer.byteLength // 32
```
- ArrayBuffer.prototype.slice():將內存區域的一部分復制生成一個新的 ArrayBuffer 對象;slice 方法包含兩步:第一步先分配一段新內存,第二步將要復制的內存區域拷貝(是否正確?)
```
var buffer = new ArrayBuffer(8)
var newBuffer = buffer.slice(0, 3) // 復制 buffer 對象的前 3 個字節(0, 1, 2)
```
- ArrayBuffer.isView():該方法返回一個布爾值,表示參數是否為 ArrayBuffer 的視圖實例
```
var buffer = new ArrayBuffer(8)
ArrayBuffer.isView(buffer) // false
var v = new Int32Array(buffer)
ArrayBuffer.isView(v) // true
```
## TypedArray 視圖
TypedArray 視圖與 DataView 視圖的區別是,前者的數組成員都是同一類型,后者的數組成員可以是不同的數據類型。
TypedArray 的每一種視圖都是一種構造函數
- Int8Array:8位有符號整數,長度為 1 字節
- Uint8Array:8位無符號整數,長度為 1 個字節
- Uint8ClampedArray:8位無符號整數,長度為 1 個字節,溢出處理不同
- Int16Array:16 位有符號整數,長度為 2 個字節
- Uint16Array:16 位無符號整數
- Int32Array:32 位有符號整數
- Uint32Array:32 位無符號整數
- Float32Array:32 位浮點數,長度為 4 個字節
- Float64Array:64 位浮點數,長度為 8 個字節
這 9 個構造函數生成的數組,統稱為 TypedArray 視圖,它們很像普通數組,都有 length 屬性,都能用方括號運算符([])獲取單個元素,所有數組方法都能在其上使用,普通數組與視圖數組的差別主要為以下幾個方面:
- TypedArray 數組的所有成員都是同一種類型
- TypedArray 數組的成員是連續的,不會有空位
- TypedArray 數組成員的默認值為 0
- TypedArray 數組只是一層視圖,本身不存儲數據,它的數據都存儲在底層的 ArrayBuffer 對象中
```
// 創建一個 8 字節的 ArrayBuffer
var b = new ArrayBuffer(8)
// 創建一個指向 b 的 Int32 視圖,開始于字節 0,直到緩沖區的末尾
var v1 = new Int32Array(b)
// 創建一個指向 b 的 Uint8 視圖,開始于字節 2,直到緩沖區的末尾
var v2 = new Uint8Array(b, 2)
// 創建一個指向 b 的 Int16 視圖,開始于字節 2,長度為2
var v3 = new Int16Array(b, 2, 2)
```
即視圖的構造函數可以接受 3 個參數:
- 第一個參數(必選):視圖對應的 ArrayBuffer 對象
- 第二個參數(可選):視圖開始的字節序號,默認從 0 開始
- 第三個參數(可選):視圖包含的數據個數,默認直到本段內存區域結束
## DataView 視圖
暫不整理......
## 二進制數組的應用
### AJAX
傳統上,服務器通過 AJAX 操作只能返回文本數據,即 responseType 屬性默認為 text,XHR2 允許服務器返回二進制數據,這時分兩種情況:如果明確知道返回的二進制數據類型,可以把返回類型(responseType)設置為 arraybuffer;如果不知道,就設置為 blob
```
var xhr = new XMLHttpRequest()
xhr.open('GET', someUrl)
xhr.responseType = 'arraybuffer'
xhr.onload = function () { // 接收到完整的響應數據時觸發
let arrayBuffer = xhr.response
// ...
}
xhr.send()
// 如果知道傳回來的是 32 位整數,可以像下面這樣處理
xhr.onreadystatechange = function () {
if (req.readyState === 4) {
var arrayResponse = xhr.response
var dataView = new DataView(arrayResponse)
var ints = new Uint32Array(dataView.byteLength / 4)
xhrDiv.innerText = `Array is ${ints.length} uints long`
}
}
```
### WebSocket
WebSocket 可以通過 ArrayBuffer 發送或接收二進制數據
### Fetch API
### File API
### SharedArrayBuffer
# 參考鏈接
[https://juejin.im/post/5b32ea55e51d4558bf7c45e0](https://juejin.im/post/5b32ea55e51d4558bf7c45e0)
[https://www.zhangxinxu.com/wordpress/2013/10/understand-domstring-document-formdata-blob-file-arraybuffer/](https://www.zhangxinxu.com/wordpress/2013/10/understand-domstring-document-formdata-blob-file-arraybuffer/)
- 序言 & 更新日志
- H5
- Canvas
- 序言
- Part1-直線、矩形、多邊形
- Part2-曲線圖形
- Part3-線條操作
- Part4-文本操作
- Part5-圖像操作
- Part6-變形操作
- Part7-像素操作
- Part8-漸變與陰影
- Part9-路徑與狀態
- Part10-物理動畫
- Part11-邊界檢測
- Part12-碰撞檢測
- Part13-用戶交互
- Part14-高級動畫
- CSS
- SCSS
- codePen
- 速查表
- 面試題
- 《CSS Secrets》
- SVG
- 移動端適配
- 濾鏡(filter)的使用
- JS
- 基礎概念
- 作用域、作用域鏈、閉包
- this
- 原型與繼承
- 數組、字符串、Map、Set方法整理
- 垃圾回收機制
- DOM
- BOM
- 事件循環
- 嚴格模式
- 正則表達式
- ES6部分
- 設計模式
- AJAX
- 模塊化
- 讀冴羽博客筆記
- 第一部分總結-深入JS系列
- 第二部分總結-專題系列
- 第三部分總結-ES6系列
- 網絡請求中的數據類型
- 事件
- 表單
- 函數式編程
- Tips
- JS-Coding
- Framework
- Vue
- 書寫規范
- 基礎
- vue-router & vuex
- 深入淺出 Vue
- 響應式原理及其他
- new Vue 發生了什么
- 組件化
- 編譯流程
- Vue Router
- Vuex
- 前端路由的簡單實現
- React
- 基礎
- 書寫規范
- Redux & react-router
- immutable.js
- CSS 管理
- React 16新特性-Fiber 與 Hook
- 《深入淺出React和Redux》筆記
- 前半部分
- 后半部分
- react-transition-group
- Vue 與 React 的對比
- 工程化與架構
- Hybird
- React Native
- 新手上路
- 內置組件
- 常用插件
- 問題記錄
- Echarts
- 基礎
- Electron
- 序言
- 配置 Electron 開發環境 & 基礎概念
- React + TypeScript 仿 Antd
- TypeScript 基礎
- React + ts
- 樣式設計
- 組件測試
- 圖標解決方案
- Storybook 的使用
- Input 組件
- 在線 mock server
- 打包與發布
- Algorithm
- 排序算法及常見問題
- 劍指 offer
- 動態規劃
- DataStruct
- 概述
- 樹
- 鏈表
- Network
- Performance
- Webpack
- PWA
- Browser
- Safety
- 微信小程序
- mpvue 課程實戰記錄
- 服務器
- 操作系統基礎知識
- Linux
- Nginx
- redis
- node.js
- 基礎及原生模塊
- express框架
- node.js操作數據庫
- 《深入淺出 node.js》筆記
- 前半部分
- 后半部分
- 數據庫
- SQL
- 面試題收集
- 智力題
- 面試題精選1
- 面試題精選2
- 問答篇
- 2025面試題收集
- Other
- markdown 書寫
- Git
- LaTex 常用命令
- Bugs