JavaScript中各種二進制對象關(guān)系的深入講解
前言
現(xiàn)代 JavaScript 要面臨更加復雜的場景,對于各種類型的數(shù)據(jù)傳輸也多了起來,其中涉及二進制傳輸,為了方便處理數(shù)據(jù)提高效率于是創(chuàng)造了ArrayBuffer對象。
但是使用中會發(fā)現(xiàn)不僅僅有ArrayBuffer,還有TypedArray、DataView、Blob、FileReader等一系列對象,讓人迷惑它們之間關(guān)系是什么?為什么有這么多的對象?帶著問題查詢了資料,試著梳理其中的關(guān)系。
各種對象的關(guān)系
ArrayBuffer
ArrayBuffer是 JavaScript 最基本的處理二進制的對象,描述的是一段連續(xù)的內(nèi)存空間,其單位是字節(jié)(byte)。
const buffer = new ArrayBuffer(32);
這樣我們就創(chuàng)建了一塊 32 字節(jié)的內(nèi)存區(qū)域,可以使用buffer.byteLength來查看其長度。
ArrayBuffer對象能做的操作不多,并且是不可編輯的。如果需要編輯數(shù)據(jù),要利用另外兩個對象TypedArray與
DataView。
TypedArray
TypedArray類型化數(shù)組,TypedArray本身不存儲任何數(shù)據(jù),只是專門用來查看ArrayBuffer數(shù)據(jù),所以稱之為,TypedArray不是某一個構(gòu)造函數(shù)名,而是一組構(gòu)造函數(shù)的統(tǒng)稱。
- Int8Array:1 比特,8 位有符號整數(shù)
- Uint8Array:1 比特,8 位無符號整數(shù)
- Uint8ClampedArray:1 比特,8 位無符號整數(shù)
- Int16Array:2 比特,16 位無符號整數(shù)
- Uint16Array:2 比特,16 位無符號整數(shù)
- Int32Array:4 比特,32 位無符號整數(shù)
- Uint32Array:4 比特,32 位無符號整數(shù)
- Float32Array:4 比特,32 位無 IEEE 浮點數(shù)
- Float64Array:8 比特,64 位無 IEEE 浮點數(shù)
- BigInt64Array:8 比特,64 為二進制有符號整數(shù)
- BigUint64Array:8 比特,64 位無符號整數(shù)
創(chuàng)建的時候可以傳入長度、typedArray、ArrayBuffer、數(shù)組。當然也可以什么都不傳入。
const uint1 = new Uint8Array(8); const uint2 = new Uint16Array(new Uint8Array(8)); const uint3 = new Uint8Array(new ArrayBuffer(8)); const uint4 = new Uint8Array([1, 2, 3]); const uint5 = new Uint8Array();
以上typedArray中,除了創(chuàng)建時傳入ArrayBuffer不會新創(chuàng)建ArrayBuffer,其他在new過程中底層都會創(chuàng)建新的ArrayBuffer。可以使用arr.buffer來訪問其引用的ArrayBuffer。
操作上普通數(shù)組的操作都能在TypedArray 中使用。但因為ArrayBuffer描述的是連續(xù)的內(nèi)存區(qū)間,所以我們無法刪除某一個值,只能分配為0,也沒辦法使用concat方法。
Uint8ClampedArray
Uint8ClampedArray相對特殊一點,在正負溢出的情況下處理不同。
其他對于存入越界數(shù)據(jù)僅保留最右邊(低位)部分,拋棄溢出數(shù)據(jù),而Uint8ClampedArray對越界數(shù)據(jù)都保存為255,對于傳入的負數(shù)保存為0。
字符的相互轉(zhuǎn)換
TypedArray不支出直接傳字符串,所以需要先轉(zhuǎn)碼一下。
String → Unit8Array
const string = "Hello"; Uint8Array.from(string.split(""), (e) => e.charCodeAt(0));
Unit8Array → String
// 使用TextDecoder對象 const u8 = Uint8Array.of(72, 101, 108, 108, 111); new TextDecoder().decode(u8); // 使用fromCharCode轉(zhuǎn)換 const u8 = Uint8Array.of(72, 101, 108, 108, 111); Array.from(u8, (e) => String.fromCharCode(e)).join("");
DataView
以上數(shù)據(jù)除了uint2變量,其他都是單一的數(shù)據(jù)類型,uint2對象這種一段內(nèi)存中存放了兩種類型數(shù)據(jù),稱之為復合視圖。JavaScript 中數(shù)據(jù)類型往往不那么單一,僅用TypedArray操作會更加麻煩,所以又有了DataView對象。DataView相對于TypedArray有著更加多種的操作方法。
const buffer = new ArrayBuffer(8); const dataView = new DataView(buffer);
提供了getInt8、getUint8、getInt16、getUint16、getInt32、getUint32、getFloat32、getFloat64方法。
參數(shù)有兩個,第一位是節(jié)序位置,第二位是字節(jié)序,非必填。返回值是相應(yīng)位置的字節(jié)數(shù)據(jù)。
const d1 = dataView.getUint8(1); const d2 = dataView.getUint8(1, true);
字節(jié)位置好理解,字節(jié)序可以閱讀《理解字節(jié)序》,總的說就是:
- 大端字節(jié)序(big endian):高位字節(jié)在前,低位字節(jié)在后,這是人類讀寫數(shù)值的方法。
- 小端字節(jié)序(little endian):低位字節(jié)在前,高位字節(jié)在后,即以 0x1122 形式儲存。
默認情況下使用的是大端字節(jié)序,如果要使用小端字節(jié)序需要傳入true。
這樣我們就有了基礎(chǔ)的二進制的讀寫方案??蓪嶋H的應(yīng)用場景中往往有更加復雜的數(shù)據(jù),所以又針對專門的場景又衍生出Blob、FileReader等對象。
Blob
Blob,是Binary Large Object(二進制大型對象)的縮寫。
與ArrayBuffer差異是,ArrayBuffer是單純的二進制數(shù)據(jù),而Blob是帶MIME類型的二進制數(shù)據(jù)。并且可以方便的從String、ArrayBuffer、TypedArray、DataView、Blob生成為Blob對象。
const blob1 = new Blob(["hello"], { type: "text/plain" }); const blob2 = new Blob([new Uint8Array([72, 101, 108, 108, 111]), " ", "world"], { type: "text/plain" });
屬性:
- size:讀取對象的字節(jié)大小。
- type:讀取寫入的MIME類型
方法:
- slice:提取Blob片段。
URL
在開發(fā)中我們獲取到圖片二進制數(shù)據(jù),我們可以轉(zhuǎn)換成base64寫入src中,但如果數(shù)據(jù)量很大,或者視頻數(shù)據(jù),就會超過其允許長度。我們可以使用URL.createObjectURL來方便的創(chuàng)建一個資源的 URL。
const url = URL.createObjectURL(blob1);
會生成類似blob:https://example.com/a6728d20-2e78-4497-9d6c-0ed61b93f11e的資源 URL,可以直接寫入src中使用。
在不用時使用URL.revokeObjectURL(url)銷毀其引用,釋放其內(nèi)存占用。
數(shù)據(jù)讀取
如果我們要查看其中數(shù)據(jù)的話,有兩種方式。
第一種,使用Response對象,可以直接讀取字符串數(shù)據(jù)或是arrayBuffer數(shù)據(jù)。
const responseText = await new Response(blob2).text(); const responseBuf = await new Response(blob2).arrayBuffer();
第二種,使用FileReader對象。
const reader = new FileReader(); reader.onload = function (e) { console.log(reader.result); }; reader.readAsText(blob2);
File
File繼承自Blob,并增加了文件相關(guān)的屬性信息。
- name:文件名
- lastModified:最后修改時間的時間戳
- lastModifiedDate:最后修改時間的Date對象
- webkitRelativePath:文件的路徑。在 input 中選擇目錄時,會設(shè)置這個屬性,非標準特性。
FileList
FileList對象是File對象的集合。一般出現(xiàn)在:
- <input type="file">控件,其中files屬性是一個FileList
- 拖拽事件中產(chǎn)生的DataTransfer對象,其中files屬性會是一個FileList
屬性:
- length:可以獲取當前FileList包含多少個File
方法:
- item(index):可獲取指定索引位置的File數(shù)據(jù),一般情況下直接使用FileList[index]替代了。
FileReader
FileReader在談Blob一節(jié)有提到過,實際上FileReader對象就是專門用來讀取Blob對象的,當然也包括擴展的File對象。
屬性:
- result:文件的內(nèi)容。
- readyState:狀態(tài)。0:未加載;1:正在加載;2:加載完成。
- error:加載數(shù)據(jù)時的錯誤信息。
事件:
- onload:加載成功后觸發(fā)。
- onerror:加載錯誤時觸發(fā)。
- onabort:加載中斷時觸發(fā)。
- onloadend:加載結(jié)束后觸發(fā)。
- onloadstart:加載開始時觸發(fā)。
- onprogress:加載中觸發(fā)。
方法:
- readAsText(blob, "utf-8"):以文本形式返回數(shù)據(jù),第二個參數(shù)可設(shè)置文本編碼。
- readAsDataURL(blob):以Data URL的形式返回數(shù)據(jù)。
- readAsArrayBuffer(blob):以ArrayBuffer形式返回數(shù)據(jù)。
- abort:中止操作。
如上面的示例,就是以文本形式返回數(shù)據(jù):
const reader = new FileReader(); reader.onload = function (e) { console.log(reader.result); }; reader.readAsText(blob2);
相關(guān)資料
- MDN 相關(guān)的關(guān)鍵字
- 現(xiàn)代 JavaScript 教程 第三部分 二進制數(shù)據(jù),文件
- 阮一峰 JavaScript 教程 瀏覽器模型相關(guān)章節(jié)
總結(jié)
到此這篇關(guān)于JavaScript中各種二進制對象關(guān)系的文章就介紹到這了,更多相關(guān)JS二進制對象關(guān)系內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
jquery實現(xiàn)select下拉框美化特效代碼分享
這篇文章主要介紹了jquery實現(xiàn)select下拉框美化特效,實現(xiàn)效果簡潔大方,推薦給大家,有需要的小伙伴可以參考下。2015-08-08靈活使用console讓js調(diào)試更簡單的方法步驟
這篇文章主要介紹了靈活使用console讓js調(diào)試更簡單的方法步驟,適當使用這些方法可以使調(diào)試更容易,更快速,更直觀,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-04-04