本文主要經過對JavaScript中數字數據與二進制數據之間的轉換,讓讀者可以瞭解在JavaScript中如何對數字類型(包括但不限於Number類型)進行處理。javascript
二進制數據在平常的JavaScript中不多遇到,可是當你使用WebSocket與後端進行數據交互時,就有可能會用到二進制的數據格式。所以,爲了更好的理解本系列中以後發佈的關於WebSocket傳輸二進制相關的內容,咱們有必要了解二進制數據在JavaScript中是如何進行操做和存儲的。html
本文內容主要爲:java
本文與WebSocket並沒有太強關聯,不過做爲在WebSocket中傳遞二進制數據的基礎知識儲備,所以放入了此係列當中。後端
若是讀者對WebSocket並不瞭解,或者說不明白它的使用場景和細節,能夠閱讀個人前一篇博客——WebSocket系列之基礎知識入門篇。函數
若是讀者想了解String類型與二進制之間的處理和轉換,能夠於都WebSocket系列稍後發佈的文章(文章發佈後會替換此段)。源碼分析
若是讀者想了解在WebSocket中如何進行二進制的傳遞和解析,能夠閱讀WebSocket系列稍後發佈的文章(文章發佈後會替換此段)。post
瞭解了爲何須要使用二進制數據,咱們來看下,在JavaScript中如何存儲和操做二進制數據。學習
首先,咱們要介紹下在JavaScript中用來存儲二進制數據的ArrayBuffer
。ui
ArrayBuffer 對象用來表示通用的、固定長度的原始二進制數據緩衝區。spa
在MDN的文檔中,咱們可以看到ArrayBuffer
的介紹。它是在JavaScript中用來進行二進制數據存儲的一種數據對象。
下面咱們經過一個示例來簡單介紹下ArrayBuffer相關操做。
const buffer = new ArrayBuffer(8);
buffer.byteLength; // 結果爲8
複製代碼
上面的示例經過建立一個長度爲8Byte的二進制數據緩衝區。緩衝區只是一個數據存儲的空間,如何對這個存儲空間進行讀取,徹底取決於使用者。例如:8個字節能夠當成是2個Int類型的數據,也能夠是一個Long類型的數據,或者4個Short型的數據。
看完了存儲數據的ArrayBuffer
,咱們來看下數據讀寫的DataView
。
DataView 視圖是一個能夠從
ArrayBuffer
對象中讀寫多種數值類型的底層接口,在讀寫時不用考慮平臺字節序問題。
這個是在MDN中關於DataView的介紹。DataView提供了大量的API接口來進行數據的讀和寫操做,咱們在後三章將會舉例進行說明。可是,首先咱們得先看下說明中提到的字節序問題。
在現有的計算機體系中,有兩種字節序:
上面所說的順序均是針對多字節對象而言,如Int類型,Long類型。以Int類型數據0x1234
爲例,若是是大端字節序,那麼數據從人類對數值的一般寫法上來看就是0x1234
;若是是小端字節序,那麼從人類對數值的一般寫法上來看,應該寫成0x3412
。
對於單字節對象如Byte類型數據而言,沒有字節序一說。
在不一樣的平臺中,可能使用不一樣的字節序,這就是所謂的字節序問題。DataView所謂的在讀寫時不須要考慮平臺字節序問題是指:同時使用DataView進行寫入和讀取的數據保持一致。
對ArrayBuffer和DataView有了一個大概的瞭解,下面讓咱們來看下它是如何進行二進制數據操做的。
本章,我以Short類型和Int類型爲例,介紹下相關操做步驟。
let buffer = new ArrayBuffer(6); // 初始化6個Byte的二進制數據緩衝區
let dataView = new DataView(buffer);
dataView.setInt16(0, 3); // 從第0個Byte位置開始,放置一個數字爲3的Short類型數據(佔2 Byte)
dataView.setInt32(2, 15); // 從第2個Byte位置開始,放置一個數字爲15的Short類型數據(佔4 Byte)
複製代碼
經過上面的示例,咱們一共初始化了6個Byte的存儲空間,使用1個Short類型(佔2 Byte)和一個Int類型(佔4 Byte)的數據進行填充。
DataView還提供了許多的API接口來進行其餘數據類型的處理,如無符號型,浮點數等。他們的使用方法和上面介紹的API相同,咱們在這裏就不一一進行介紹了,但願瞭解更多API接口的讀者能夠查看MDN文檔。
經過DataView提供的API接口,咱們知道了如何處理Short類型、Int類型、Float類型和Double類型。那麼,若是是對於Long類型這種原生API中沒有提供處理函數的數據類型,咱們應該如何處理呢?
首先,咱們須要理解Long數據類型的結構,它是由一個高位的4個Byte和低位的4個Byte組成的數據類型。由於Long類型表示的範圍比Number類型大,因此咱們在JavaScript中是使用了兩個Number類型(即Int類型)的對象來表示Long類型數據,相關的具體細節能夠見我以前的博客Long.js源碼分析與學習。
理解了JavaScript中如何存儲Long類型,咱們就知道若是對其進行存儲。
import Long from 'long';
let long = Long.fromString('123');
let buffer = new ArrayBuffer(8);
let dataView = new DataView(buffer);
dataView.setInt32(0, long.high); // 採用大端字節序放置
dataView.setInt32(4, long.low);
複製代碼
經過上面的示例,咱們將一個Long類型的數據拆分紅了兩個Int類型的數據,按照大端字節序放入到了ArrayBuffer中。同理,若是是想按照小端字節序放置,只須要將數據進行部分處理後再放入便可,在此我就不過多介紹了。
當你知道了如何將數據轉換爲ArrayBuffer中存儲的二進制數據後,就可以簡單推測出如何進行反向操做——將數據從ArrayBuffer中讀取出來,再轉換成JavaScript中經常使用數據類型。
import Long from 'long';
let buffer = new ArrayBuffer(14); // 初始化14個Byte的二進制數據緩衝區
let dataView = new DataView(buffer);
let long = Long.fromString('123');
// 數據寫入過程
dataView.setInt16(0, 3); // 從第0個Byte位置開始,放置一個數字爲3的Short類型數據(佔2 Byte)
dataView.setInt32(2, 15); // 從第2個Byte位置開始,放置一個數字爲15的Short類型數據(佔4 Byte)
dataView.setInt32(6, long.high); // 採用大端字節序放置
dataView.setInt32(10, long.low);
// 數據讀取過程
let shortNumber = dataView.getInt16(0);
let intNumber = dataView.getInt32(2);
let longNumber = Long.fromBits(dataView.getInt32(10), dataView.getInt32(6)); // 根據大端字節序讀取,該構造函數入參依次爲:低16位,高16位
複製代碼
經過上面的示例,咱們將一串二進制數據轉換成爲了JavaScript中通用的數據類型。
經過使用ArrayBuffer和DataView,咱們可以快速的將數字數據從二進制轉換爲JavaScript經常使用數據類型如Int、Short等;同時,咱們也能夠將這些數據類型轉換爲二進制數據。有了這些基礎知識,咱們就可以理解在以後的博客中講到的關於使用WebSocket進行二進制數據傳遞的過程和處理邏輯。
下一篇博客咱們將介紹String類型相關的二進制處理與轉換操做,有興趣的同窗能夠關注留意下相關內容。