JS的二進位制操作

沒有角的牛發表於2019-02-16

之前在某個專案中,遇到了許多JS的二進位制操作場景,因此總結下JS中的二進位制操作方法。

所謂二進位制操作,是指操作變數實際儲存的值,比如獲取字元A的Unicode值,或者將值100填入到8個位元組中。

1. 位操作符

JS中的位操作與很多語言類似,具體的位運算子如下表所示。

運算子 用法 描述
按位與 a & b 對於每一個位元位,只有兩個運算元相應的位元位都是1時,結果才為1,否則為0。
按位或 a | b 對於每一個位元位,當兩個運算元相應的位元位至少有一個1時,結果為1,否則為0。
按位異或 a ^ b 對於每一個位元位,當兩個運算元相應的位元位有且只有一個1時,結果為1,否則為0。
按位非 ~ a 反轉運算元的位元位,即0變成1,1變成0。
左移 a << b 將 a 的二進位制形式向左移 b (< 32) 位元位,右邊用0填充。
有符號右移 a >> b 將 a 的二進位制表示向右移 b (< 32) 位,丟棄被移出的位。
無符號右移 a >>> b 將 a 的二進位制表示向右移 b (< 32) 位,丟棄被移出的位,並使用 0 在左側填充。

2. 字元和Unicode編碼

在介紹具體的方法前,我們需要先了解下UCS-2和UTF-16編碼。

UCS-2是一個16bit長度的編碼集,它的表示範圍是0到0xFFFF。UTF-16的表示範圍是0到0x10FFFF,它由1個或者2個16bit的編碼單元組成。其中UCS-2是UTF-16的子集,UTF-16編碼在0到0x00FFFF的範圍稱為BMP(基本多文種平面),BMP與UCS-2的編碼完全一致。

更詳細的說明可以參考這裡

2.1 String.fromCharCode

fromCharCode 方法返回指定的UCS-2編碼對應的字串。它是String上的靜態方法,不可通過字串物件直接訪問。

因為入參是UCS-2編碼值,所以不能多於16bit,即入參值要小於65536。如果入參需要大於65536,可以使用 String.fromCodePoint

String.fromCharCode(65) // A
String.fromCharCode(65, 66, 68) // ABD

2.2 String.prototype.charCodeAt

charCodeAt 返回字串指定位置的字元的UTF-16編碼。該方法可以直接從字串物件進行呼叫。

如果該字元不能使用一個UTF-16編碼單元(16bit)來表示時,該方法只會返回第一個編碼單元。如果需要獲取完整的編碼,可以使用 String.prototype.codePointAt

"AB".charCodeAt(0) // 65
"AB".charCodeAt(1) // 66

3. ArrayBuffer

ArrayBuffer用來表示原始的二進位制資料快取區,但是不可直接對ArrayBuffer進行操作,需要藉助DataView或者型別陣列物件來對快取區的內容進行讀寫。

3.1 DataView

DataView 可以理解為資料視窗,通過 DataView 物件可以對 ArrayBuffer 進行讀寫操作。

const buffer = new ArrayBuffer(4); // 申請2個位元組長度的快取區
const view1 = new DataView(buffer); // view1的範圍是整個快取區
const view2 = new DataView(buffer, 2, 1) // view2的範圍是從第2個位元組開始往後的一個位元組

// 向一個16bit的內容中填入一個帶符號的數
// 引數的含義依次為 輸入內容的位置、輸入的值、是否使用小端方式(預設大端)
view1.setInt16(0, 0x0A0B, false);
view1.getInt8(0); // 10,即0x0A
view1.getInt8(1); // 11,即0x0B

view2.setUint8(0, 255);
view2.getInt8(0); // 按照有符號數來讀取,結果為-1

更多的操作方法可以參考DataView

3.2 型別陣列物件

型別陣列物件有很多種,比如Uint8Array, Int32Array等。將ArrayBuffer轉化為型別陣列後,就可以像陣列一樣來操作快取區。

const buffer = new ArrayBuffer(8);

const arr1 = new Int16Array(buffer);
const arr2 = new Uint8Array(buffer);

arr1[0] = 256;
arr2[6] = 255;

console.log(arr1); // [256, 0, 0, 255]
console.log(arr2); // [0, 1, 0, 0, 0, 0, 255, 0]

參考文獻

  1. 按位操作符 – JavaScript | MDN
  2. Unicode字元平面對映
  3. JavaScript’s internal character encoding: UCS-2 or UTF-16?
  4. String.fromCharCode() – JavaScript | MDN
  5. String.prototype.charCodeAt() – JavaScript | MDN
  6. ArrayBuffer – JavaScript | MDN

相關文章