理解 typed array

咱們知道在C語言中,可使用mallocfree方法來分配和釋放內存。隨着web的發展中,js在ES6中新增了內存操做的支持。其實現方式就是---typed array。web

typed array是個集體的概念。int8Array,Uint8Array,int16Array,Uint16Array等通通等稱爲typed array。經過這些類,開發者能夠方便地讀寫內存中的二進制數據。數組

typed array在內部設計時分紅了兩部分:bufferviewbuffer層表示內存中的數據塊,view負責提供操做數據塊的接口。spa

ArrayBuffer

buffer層的底層實現就是基於ArrayBuffer類。ArrayBuffer的功能與malloc相似,爲用戶分配一塊內存。設計

建立一個ArrayBuffer實例很簡單,它接收一個參數,參數表示要分配多大的一塊內存區域,字節爲單位。下面的代碼片斷,分配了一塊8字節的內存區:code

var buffer = new ArrayBuffer(8);

咱們還能夠經過byteLength訪問該實例的內存大小:對象

console.log(buffer.byteLength) // 8

使用slice方法建立一個新的實例,其內容複製原ArrayBuffer實例中的部份內容。索引

var buf2 = buffer.slice(0,2);

建立一個新的實例,分配2字節大小的內存,其內容複製buffer中索引爲0和1的內存中的數據。接口

可是ArrayBuffer並不提供對內存讀寫的方法。若是要對該內存塊進行操做,須要用到另外一個類DataView圖片

DataView

DataView類提供了訪問ArrayBuffer的接口。其語法以下:內存

new DataView(buffer [, byteOffset [, byteLength]])

首先接收一個必傳的buffer對象,該對象就是DataView實例接下來將要操做的內存塊。其次是一個可選的byteOffset,該參數表示DataView實例要操做的buffer對象的開始位置。最後的參數指定要操做的buffer對象中元素的個數。
下面的代碼片斷演示了DataView如何操做ArrayBuffer

var buffer = new ArrayBuffer(16);
var dv = new DataView(buffer, 0);

dv.setInt16(1, 42);
dv.getInt16(1); //42

示例中建立了一個DataView實例,該實例將buffer做爲被操做的內存塊,而且指定該內存塊的16個字節都位於可操做區。
接着調用setInt16方法向從buffer的第2個字節開始存儲帶符號的16位整數。調用getInt16方法讀出位於第2個字節處的帶符號的16位整數。

typed array

如上所述,typed array的實現是組合了ArrayBufferDataView。也就是說typed array 經過ArrayBuffer建立內存塊,經過DataView實現對內存塊的讀寫操做。

typed array提供了多個類實現對同一塊內存中的二進制數據按照不一樣的位數格式進行讀寫。如使用int8Array從內存中以帶符號的8位整數的形式讀寫數據。

下面看一個例子來加深對typed array的理解

var buffer = new ArrayBuffer(16) //建立16b的內存區
var int32View = new Int32Array(buffer);
var int16View = new Int16Array(buffer);

for (var i = 0; i < int32View.length; i++) {
  int32View[i] = i * 2;
  console.log(int32View[i]); // 0, 2, 4, 6
}

for (var i = 0; i < int16View.length; i++) {
  console.log(int16View[i]); // 0, 0, 2, 0, 4, 0, 6, 0
}

buffer是一個ArrayBuffer實例,表示一塊16b的內存區。同時建立了兩個typed array,分別是32位和16位的。區別在於使用32位的訪問buffer時,會把buffer(16b)以32位爲單位劃分爲4個元素,讀寫都是以32位爲單位進行的。16位的進行訪問時,會把buffer(16b)以16位爲單位劃分爲8個元素,每次讀寫都是16位。

第一個循環中,咱們使用int32Viewbuffer中的4個元素中分別寫入了0,2,4,6 4個整數。
很顯然console中的結果是0,2,4,6

第二個循環中,咱們使用int16View以16位的格式讀取同一塊內存,能夠想象原來的4個元素變成了8個元素,所以讀出的時候也會將原來的32位元素拆分爲2個16位元素。所以console中的結果是0,0,2,0,4,0,6,0

有同窗可能對輸出的順序不理解,以爲爲何不是0,0,0,2,0,4,0,6呢。這裏稍微解釋一下。
緣由是默認狀況下typed array 讀取數據的時候都是以小端模式來返回的。

所謂的小端模式(Little-endian),是指數據的高字節保存在內存的高地址中,而數據的低字節保存在內存的低地址中,這種存儲模式將地址的高低和數據位權有效地結合起來,高地址部分權值高,低地址部分權值低,和咱們的邏輯方法一致。

上例在小端模式下的存儲形式,每一個框框表示16位。小端模式下數據的位權和地址的順序是一致的,從小到大排列。

圖片描述

總結

typed array提供了一組讀取不一樣字長的類數組對象如,int8Array,int16Array,int64Array來實現對內存的操做。typed array的底層實現是基於ArrayBufferDataView實現的,對內存的分配和內存的讀取作了很好的分層設計。使用typed array使js向C語言等具有了操做二進制數據的能力。

相關文章
相關標籤/搜索