ES6學習筆記---二進制數組(概念)

二進制數組由三類對象組成:javascript

  • ArrayBuffer對象:表明原始的二進制數據。java

  • TypedArray視圖:用來讀寫簡單類型的二進制數據。數組

  • DataView視圖:用來讀寫複雜類型的二進制數據。app

下面詳細瞭解一下它們的用法:函數

1. ArrayBuffer 對象

它不能直接讀寫,只能經過(TypedArrayDataView)來讀寫。ui

ArrayBuffer也是一個構造函數,能夠分配一段能夠存放數據的連續內存區域。編碼

例如我想生成一段32字節的內存區域,每一個字節的值默認都是0,就能夠這樣建立:prototype

var buf = new ArrayBuffer(32);

ArrayBuffer.prototype.byteLength

byteLength:是ArrayBuffer實例的屬性,返回所分配的內存區域的字節長度。code

var buffer = new ArrayBuffer(32);
buffer.byteLength     // 32

須要注意的是:若是你想分配一塊比較大的內存區域,須要檢查是否分配成功,由於可能沒有那麼多的連續空餘內存。orm

if(buffer.byteLength === n){
    //成功
}else{
    //失敗
}

ArrayBuffer.prototype.slice()

slice:有兩個參數,第一個參數表示開始拷貝的字節序號(包含此字節),第二個參數表示截止拷貝的字節序號(不含此字節),若是省略第二個參數,則默認截止到原ArrayBuffer對象的結尾。

slice:是ArrayBuffer實例的一個方法,容許將內存區域的一部分,拷貝生成一個新的ArrayBuffer對象。

var buffer = new ArrayBuffer(8);
var newBuffer = buffer.slice(0, 3);
//拷貝`buffer`對象的前三個字節(從0到3前結束),生成一個新的ArrayBuffer對象:newBuffer

ArrayBuffer.isView()

isView:是ArrayBuffer的一個靜態方法,返回一個布爾值,表示參數是否爲ArrayBuffer的視圖實例。這個方法大體至關於判斷參數,是否爲TypedArray實例或DataView實例。

var buffer = new ArrayBuffer(8);
ArrayBuffer.isView(buffer) // false

var v = new Int32Array(buffer);
ArrayBuffer.isView(v) // true

2. TypedArray 視圖

TypedArray數組只提供9種固定的構造函數,用來生成相應類型的數組實例。

(1)TypedArray(buffer, byteOffset=0, length?)

視圖的構造函數能夠接受三個參數:

  • 第一個參數(必需):視圖對應的底層ArrayBuffer對象。

  • 第二個參數(可選):視圖開始的字節序號,默認從0開始。

  • 第三個參數(可選):視圖包含的數據個數,默認直到本段內存區域結束。

// 建立一個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);

v1[0]是一個32位整數,指向字節0~字節3;v2[0]是一個8位無符號整數,指向字節2;v3[0]是一個16位整數,指向字節2~字節3。只要任何一個視圖對內存有所修改,就會在另外兩個視圖上反應出來。

注:byteOffset必須與所要創建的數據類型一致,好比:帶符號的16位整數須要兩個字節,因此byteOffset參數必須可以被2整除

(2)TypedArray(length)

視圖還能夠不經過ArrayBuffer對象,直接分配內存而生成。

var f64a = new Float64Array(8); //64字節
f64a[0] = 10;
f64a[1] = 20;
f64a[2] = f64a[0] + f64a[1]; // 30

(3)TypedArray(typedArray)

TypedArray數組的構造函數,能夠接受另外一個TypedArray實例做爲參數。

var typedArray = new Int8Array(new Uint8Array(4));

注:新數組會開闢一段新的內存存數據。

var x = new Int8Array([1, 1]);
var y = new Int8Array(x);
x[0] // 1
y[0] // 1

x[0] = 2;
y[0] // 1

//基於同一段內存
var x = new Int8Array([1, 1]);
var y = new Int8Array(x.buffer);
x[0] // 1
y[0] // 1

x[0] = 2;
y[0] // 2

(4)TypedArray(arrayLikeObject)

//普通數組生成TypedArray實例
var typedArray = new Uint8Array([1, 2, 3, 4]);
//這時TypedArray視圖會從新開闢內存,不會在原數組的內存上創建視圖


//TypedArray數組轉換回普通數組
var normalArray = Array.prototype.slice.call(typedArray);

須要注意的是:TypedArray數組除了沒有concat方法以外,擁有普通數組全部的操做方法和屬性

若是想要合併多個TypedArray數組,能夠用下面這個函數。

function concatenate(resultConstructor, ...arrays) {
  let totalLength = 0;
  for (let arr of arrays) {
    totalLength += arr.length;
  }
  let result = new resultConstructor(totalLength);
  let offset = 0;
  for (let arr of arrays) {
    result.set(arr, offset);
    offset += arr.length;
  }
  return result;
}

concatenate(Uint8Array, Uint8Array.of(1, 2), Uint8Array.of(3, 4))
// Uint8Array [1, 2, 3, 4]

TypedArray數組也能夠被遍歷。

let ui8 = Uint8Array.of(0, 1, 2);
for (let byte of ui8) {
  console.log(byte);
}
// 0
// 1
// 2

ArrayBuffer 與字符串的互相轉換

注:字符串的編碼方法是肯定的,才能夠相互轉換。

// ArrayBuffer轉爲字符串,參數爲ArrayBuffer對象
function ab2str(buf) {
  return String.fromCharCode.apply(null, new Uint16Array(buf));
}

// 字符串轉爲ArrayBuffer對象,參數爲字符串
function str2ab(str) {
  var buf = new ArrayBuffer(str.length * 2); // 每一個字符佔用2個字節
  var bufView = new Uint16Array(buf);
  for (var i = 0, strLen = str.length; i < strLen; i++) {
    bufView[i] = str.charCodeAt(i);
  }
  return buf;
}

TypedArray.prototype.buffer:返回整段內存區域對應的ArrayBuffer對象,屬性爲只讀。

TypedArray.prototype.byteLength:返回TypedArray數組佔據的內存長度,單位爲字節,屬性爲只讀。

TypedArray.prototype.byteOffset:返回TypedArray數組從底層ArrayBuffer對象的哪一個字節開始,屬性爲只讀。

TypedArray.prototype.length:TypedArray數組含有多少個成員。

TypedArray.prototype.set():用於複製數組(普通數組或TypedArray數組)。

TypedArray.prototype.subarray():對於TypedArray數組的一部分,再創建一個新的視圖。

TypedArray.prototype.slice():返回一個指定位置的新的TypedArray實例。

TypedArray.of():用於將參數轉爲一個TypedArray實例。

TypedArray.from():返回一個基於這個結構的TypedArray實例。

3. 複合視圖

var buffer = new ArrayBuffer(24);

var idView = new Uint32Array(buffer, 0, 1);
var usernameView = new Uint8Array(buffer, 4, 16);
var amountDueView = new Float32Array(buffer, 20, 1);

上面代碼將一個24字節長度的ArrayBuffer對象,分紅三個部分:

  • 字節0到字節3:1個32位無符號整數

  • 字節4到字節19:16個8位整數

  • 字節20到字節23:1個32位浮點數

4. DataView視圖

DataView實例有如下屬性,含義與TypedArray實例的同名方法相同。

  • DataView.prototype.buffer:返回對應的ArrayBuffer對象

  • DataView.prototype.byteLength:返回佔據的內存字節長度

  • DataView.prototype.byteOffset:返回當前視圖從對應的ArrayBuffer對象的哪一個字節開始

DataView實例提供8個方法讀取內存。

  • getInt8:讀取1個字節,返回一個8位整數。

  • getUint8:讀取1個字節,返回一個無符號的8位整數。

  • getInt16:讀取2個字節,返回一個16位整數。

  • getUint16:讀取2個字節,返回一個無符號的16位整數。

  • getInt32:讀取4個字節,返回一個32位整數。

  • getUint32:讀取4個字節,返回一個無符號的32位整數。

  • getFloat32:讀取4個字節,返回一個32位浮點數。

  • getFloat64:讀取8個字節,返回一個64位浮點數。

DataView視圖提供8個方法寫入內存。

  • setInt8:寫入1個字節的8位整數。

  • setUint8:寫入1個字節的8位無符號整數。

  • setInt16:寫入2個字節的16位整數。

  • setUint16:寫入2個字節的16位無符號整數。

  • setInt32:寫入4個字節的32位整數。

  • setUint32:寫入4個字節的32位無符號整數。

  • setFloat32:寫入4個字節的32位浮點數。

  • setFloat64:寫入8個字節的64位浮點數。

相關文章
相關標籤/搜索