咱們知道在C語言中,可使用malloc
和free
方法來分配和釋放內存。隨着web的發展中,js在ES6中新增了內存操做的支持。其實現方式就是---typed array。web
typed array是個集體的概念。int8Array
,Uint8Array
,int16Array
,Uint16Array
等通通等稱爲typed array。經過這些類,開發者能夠方便地讀寫內存中的二進制數據。數組
typed array在內部設計時分紅了兩部分:buffer
和view
。buffer
層表示內存中的數據塊,view
負責提供操做數據塊的接口。spa
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
類提供了訪問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的實現是組合了ArrayBuffer
和DataView
。也就是說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位。
第一個循環中,咱們使用int32View
向buffer
中的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的底層實現是基於ArrayBuffer
和DataView
實現的,對內存的分配和內存的讀取作了很好的分層設計。使用typed array使js向C語言等具有了操做二進制數據的能力。