JavaScript中你所不知道的陣列ArrayBuffer
導讀 | 相信每一個 javascript 學習者,都會去了解 JS 的各種基本資料型別,陣列就是資料的組合,這是一個很基本也十分簡單的概念,他的內容沒多少,學好它也不是件難事情。但是本文著重要介紹的並不是我們往常看到的 Array,而是 ArrayBuffer。 |
前段時間一直在研究 Web Audio API 以及語音通訊相關的知識,內容側重於音訊流在 AudioContext 各個節點之間的流動情況,而現在要摸清楚音訊到流底是個什麼樣的資料格式,所以對 ArrayBuffer 的研究就顯得格外重要了。
Javascript 中如何產生 Array:
[element0, element1, ..., elementN] new Array(element0, element1, ..., elementN) new Array(arrayLength)
直接定義,或者透過建構函式建立一個 Array,當然也可以使用其他的手段:
"array".split(""); "array".match(/a|r/g);
等等,方式有很多。但是 Array 內部是個什麼樣的結構,恐怕很多人還不是很清楚。
在陣列中我們可以放很多不同資料型別的資料,如:
var arr = [21, "李靖", new Date(), function(){}, , null];
上面這個陣列中一次放入了 數字、字串、物件、函式、undefined 和 null,對於上面的資料介面我們可以具象的描述下:
棧 +---------+ 堆 | 21 | +-------------------+ +---------+ | | | "李靖" | | | +---------+ | +--------+ | | [refer] |----------->| Object | | +---------+ | +--------+ | | [refer] |----------------->+--------+ | +---------+ | |function| | |undefined| | +--------+ | +---------+ | | | null | +-------------------+ +---------+ Created By Barret Lee
JavaScript 的資料型別分為兩種,一種是值型別,一種是引用型別,常見的引用型別有 Object 和 Array,陣列的儲存模型中,如果是諸如 Number、String 之類的值型別資料會被直接壓入棧中,而引用型別只會壓入對該值的一個索引,用 C 語言的概念來解釋就是隻儲存了資料的指標,這些資料是儲存在堆中的某塊區間中。棧堆並不是獨立的,棧也可以在堆中存放。
好了,對 Array 的說明就到這裡,下面具體說說 ArrayBuffer 的相關知識。
web 是個啥玩意兒,web 要討論的最基本問題是什麼?我覺得有兩點,一個是資料,一個是資料傳輸,至於資料的展示,紛繁複雜,這個應該是 web 上層的東西。而本文要討論的 ArrayBuffer 就是最基礎的資料型別,甚至不能稱之為資料型別,它是一個資料容易,需要透過其他方式來讀寫。
官方點的定義:
The ArrayBuffer is a data type that is used to represent a generic, fixed-length binary data buffer. You can't directly manipulate the contents of an ArrayBuffer; instead, you create an ArrayBufferView object which represents the buffer in a specific format, and use that to read and write the contents of the buffer.
表示二進位制資料的原始緩衝區,該緩衝區用於儲存各種型別化陣列的資料。 無法直接讀取或寫入 ArrayBuffer,但可根據需要將其傳遞到型別化陣列或 DataView 物件 來解釋原始緩衝區。
他是一個二進位制資料的原始緩衝區,雖然 JavaScript 是弱型別語言,但是他本身是對資料的型別和大小都有限制的,我們需要透過某種資料結構將緩衝區的內容有序的讀取出來(寫進去)。
透過 ArrayBuffer 這個建構函式可以建立一個原始緩衝區:
var buffer = new ArrayBuffer(30);
從 chrome 控制檯可以看到:
[![arrayBuffer]({{ site.repo }}/images/blog-article-images/blog/audio/arraybuffer.jpg)]({{ site.repo }}/images/blog-article-images/blog/audio/arraybuffer.jpg)
buffer 例項擁有一個 byteLength 的屬性,用於獲取 buffer 的 size,一個只有 IE11+ 以及 ios6+ 支援的 slice 方法,用於對 buffer 長度進行擷取操作。
ArrayBuffer slice( unsigned long begin unsigned long end Optional );
可以測試這個 DEMO:
var buffer = new ArrayBuffer(12); var x = new Int32Array(buffer); x[1] = 1234; var slice = buffer.slice(4); var y = new Int32Array(slice); console.log(x[1]); console.log(y[0]); x[1] = 6789; console.log(x[1]); console.log(y[0]);
型別化陣列型別表示可編制索引和操縱的 ArrayBuffer 物件 的各種檢視。 所有陣列型別的長度均固定。
名稱 | 大小(以位元組為單位) | 描述 |
---|---|---|
Int8Array | 1 | 8 位二補碼有符號整數 |
Uint8Array | 1 | 8 位無符號整數 |
Int16Array | 2 | 16 位二補碼有符號整數 |
Uint16Array | 2 | 16 位無符號整數 |
Int32Array | 4 | 32 位二補碼有符號整數 |
Uint32Array | 4 | 32 位無符號整數 |
Float32Array | 4 | 32 位 IEEE 浮點數 |
Float64Array | 8 | 64 位 IEEE 浮點數 |
Int 就是整型,Uint 為無符號整形,Float 為浮點型,這些是 C 語言中的基本概念,我就不具體解釋了。由於這些檢視化結構都是大同小異,本文只對 Float32Array 型別作說明,讀者可以舉一反三。
Float32Array 跟 Array 是十分類似的,只不過他每一個元素都是都是一個 32位(4位元組) 的浮點型資料。Float32Array 一旦建立其大小不能再修改。
我們可以直接建立一個 Float32Array:
var x = new Float32Array(2); x[0] = 17; console.log(x[0]); // 17 console.log(x[1]); // 0 console.log(x.length); // 2
需要有這麼一個概念,他依然是一個陣列,只不過該陣列中的每個元素都是 Float 32 位的資料型別,再如:
var x = new Float32Array([17, -45.3]); console.log(x[0]); // 17 console.log(x[1]); // -45.29999923706055 console.log(x.length); // 2
我們把一個陣列的值直接賦給了 x 這個 Float32Array 物件,那麼在儲存之前會將它轉換成一個 32位浮點數。
由於該類陣列的每個元素都是同一型別,所以在堆疊模型中,他們全部會被壓入到棧之中,因此型別化陣列都是值型別,他並不是引用型別!這個要引起注意,從下面的例子中也可以反映出來:
var x = new Float32Array([17, -45.3]); var y = new Float32Array(x); console.log(x[0]); // 17 console.log(x[1]); //-45.29999923706055 console.log(x.length); // 2 x[0] = -2; console.log(y[0]); // 17, y的值沒變
將 x 的值複製給 y,修改 x[0], y[0] 並沒有變化。
除了上面的方式,我們還可以透過其他方式來建立一個型別化陣列:
var buffer = new ArrayBuffer(12); var x = new Float32Array(buffer, 0, 2); var y = new Float32Array(buffer, 4, 1); x[1] = 7; console.log(y[0]); // 7
解釋下這裡為什麼返回 7.
ArrayBuffer(12) +-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|1|2|3|4|5|6|7|8| | | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+ \ / x (Float32Array) offset:0 byteLength:4 length:2 ArrayBuffer(12) +-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|1|2|3|4|5|6|7|8| | | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+ \ / y
看了上面的圖解還有疑問麼?我覺得我不用繼續解釋了。可以把 ArrayBuffer 的單位看成 1,而 Float32Array 的單位是 4.
DataView 物件對資料的操作更加細緻,不過我覺得沒啥意思,上面提到的各種型別化陣列已經可以基本滿足應用了,所以這裡就一筆帶過,一個簡單的示例:
var buffer = new ArrayBuffer(12); var x = new DataView(buffer, 0); x.setInt8(0, 22); x.setFloat32(1, Math.PI); console.log(x.getInt8(0)); // 22 console.log(x.getFloat32(1)); // 3.1415927410125732
ArrayBuffer 的應用特別廣泛,無論是 WebSocket、WebAudio 還是 Ajax等等,前端方面只要是處理大資料或者想提高資料處理效能,那一定是少不了 ArrayBuffer 。
XHR2 並不是什麼新東西,可能你用到了相關的特性,卻不知這就是 XHR2 的內容。最主要的一個東西就是 “xhr.responseType”,他的作用是設定響應的資料格式,可選引數有:"text"、"arraybuffer"、"blob"或"document"。請注意,設定(或忽略)xhr.responseType = '' 會預設將響應設為"text"。這裡存在一個這樣的對應關係:
請求 響應 text DOMString arraybuffer ArrayBuffer blob Blob document Document
舉個例子:
var xhr = new XMLHttpRequest(); xhr.open('GET', '/path/to/image.png', true); xhr.responseType = 'arraybuffer'; xhr.onload = function(e) { // this.response == uInt8Array.buffer var uInt8Array = new Uint8Array(this.response); }; xhr.send();
我們在 xhr.responseType 中設定了屬性為 arraybuffer,那麼在拿到的資料中就可以用型別化陣列來接受啦!
本文主要介紹了 Array 在堆疊模型中的存放方式,也詳細描述了 ArrayBuffer 這個原始緩衝區的二進位制資料型別,在 web 開發中,資料以及資料的儲存是一個重要的部分,希望引起注意!
- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array MDN Array
- html5rocks
- MSDN
原文來自:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69955379/viewspace-2933017/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 你所不知道的JavaScript 二JavaScript
- 你所不知道的JavaScript(三)JavaScript
- 提升----你所不知道的JavaScript系列(3)JavaScript
- 閉包—-你所不知道的JavaScript系列(4)JavaScript
- JavaScript ArrayBufferJavaScript
- Javascript中的陣列物件排序JavaScript陣列物件排序
- JavaScript中對陣列和陣列API的認識JavaScript陣列API
- Python中你所不知道的“隱藏技巧”!Python
- 你所不知道的 Transformer!ORM
- 你所不知道的cssCSS
- 你所不知道的 POST
- Javascript - 陣列和陣列的方法JavaScript陣列
- Javascript建立陣列的方式你瞭解了嗎JavaScript陣列
- 關於JavaScript物件,你所不知道的事(一)- 先談物件JavaScript物件
- 精讀《你不知道的javascript》中卷JavaScript
- 你所不知道的XML安全XML
- JavaScript 中陣列 sort() 方法的基本使用JavaScript陣列
- JavaScript陣列方法總結(中)JavaScript陣列
- JavaScript 中實現等分陣列JavaScript陣列
- 你不知道的簡單陣列拷貝方法全解陣列
- 關於JavaScript物件,你所不知道的事(二)- 再說屬性JavaScript物件
- JavaScript 陣列JavaScript陣列
- 《你不知道的JavaScript》 (中) 讀書筆記JavaScript筆記
- 你不知道的JavaScript(中) - 閱讀筆記JavaScript筆記
- 你所不知道的 AI 進展AI
- JavaScript之你不知道的thisJavaScript
- 你不知道的JavaScript(二)JavaScript
- 你不知道的JavaScript(一)JavaScript
- JavaScript 中的陣列分組:array.groupBy()JavaScript陣列
- Javascript中陣列方法reduce的妙用之處JavaScript陣列
- 從JavaScript中的類陣列物件說起JavaScript陣列物件
- JavaScript獲取元素在陣列中的位置JavaScript陣列
- 【譯】關於JavaScript 陣列你應該知道的事情JavaScript陣列
- JavaScript 陣列操作JavaScript陣列
- JavaScript 陣列排序JavaScript陣列排序
- JavaScript 陣列 toString()JavaScript陣列
- JavaScript—陣列(17)JavaScript陣列
- JavaScript 陣列 slice()JavaScript陣列