你所不知道的JavaScript數組

來源:互聯網
上載者:User

標籤:

                                                       你所不知道的JavaScript數組

相信每一個 javascript 學習者,都會去瞭解 JS 的各種基礎資料型別 (Elementary Data Type),數組就是資料的組合,這是一個很基本也十分簡單的概念,他的內容沒多少,學好它也不是件難事情。但是本文著重要介紹的並不是我們往常看到的 Array,而是 ArrayBuffer。

我寫的很多東西都是因為要完成某些特定的功能而刻意總結的,可以算是備忘,本文也是如此!前段時間一直在研究 Web Audio API 以及語音通訊相關的知識,內容側重於音頻流在 AudioContext 各個節點之間的流動情況,而現在要摸清楚音頻到流底是個什麼樣的資料格式,所以對 ArrayBuffer 的研究就顯得格外重要了。

一、Array 在記憶體中的堆棧模型1. Array 的擷取

Javascript 中如何產生 Array:

[element0, element1, ..., elementN]new Array(element0, element1, ..., elementN)new Array(arrayLength)

直接定義,或者通過建構函式建立一個 Array,當然也可以使用其他的手段:

"array".split("");"array".match(/a|r/g);

等等,方式有很多。但是 Array 內部是個什麼樣的結構,恐怕很多人還不是很清楚。

2. 堆棧模型

在數組中我們可以放很多不同資料類型的資料,如:

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 的相關知識。

二、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 是弱類型語言,但是他本身是對資料的類型和大小都有限制的,我們需要通過某種資料結構將緩衝區的內容有序的讀取出來(寫進去)。

1. 原始緩衝區的建立

通過 ArrayBuffer 這個建構函式可以建立一個原始緩衝區:

var buffer  = new ArrayBuffer(30);

從 chrome 控制台可以看到:

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]);
運行代碼2. 類型化數組

類型化數群組類型表示可編製索引和操縱的 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]); // 17console.log(x[1]); // 0console.log(x.length); // 2
運行代碼

需要有這麼一個概念,他依然是一個數組,只不過該數組中的每個元素都是 Float 32 位的資料類型,再如:

var x = new Float32Array([17, -45.3]);console.log(x[0]);  // 17console.log(x[1]);  // -45.29999923706055console.log(x.length); // 2
運行代碼

我們把一個數組的值直接賦給了 x 這個 Float32Array 對象,那麼在儲存之前會將它轉換成一個 32位浮點數。

由於該類數組的每個元素都是同一類型,所以在堆棧模型中,他們全部會被壓入到棧之中,因此類型化數組都是實值型別,他並不是參考型別!這個要引起注意,從下面的例子中也可以反映出來:

var x = new Float32Array([17, -45.3]);var y = new Float32Array(x);console.log(x[0]); // 17console.log(x[1]); //-45.29999923706055console.log(x.length); // 2x[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      Created By Barret Lee

看了上面的圖解還有疑問嗎?我覺得我不用繼續解釋了。可以把 ArrayBuffer 的單位看成 1,而 Float32Array 的單位是 4.

3. DataView對象

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)); // 22console.log(x.getFloat32(1)); // 3.1415927410125732
運行代碼

如果感興趣,可以移步http://www.javascripture.com/DataView,作詳細瞭解。

三、XHR2 中的 ArrayBuffer

ArrayBuffer 的應用特別廣泛,無論是 WebSocket、WebAudio 還是 Ajax等等,前端方面只要是處理大資料或者想提高資料處理效能,那一定是少不了 ArrayBuffer 。

XHR2 並不是什麼新東西,可能你用到了相關的特性,卻不知這就是 XHR2 的內容。最主要的一個東西就是 xhr.responseType,他的作用是設定響應的資料格式,選擇性參數有:"text"、"arraybuffer"、"blob"或"document"。請注意,設定(或忽略)xhr.responseType = ‘‘ 會預設將響應設為"text"。這裡存在一個這樣的對應關係:

請求            響應text            DOMStringarraybuffer     ArrayBufferblob            Blobdocument        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 開發中,資料以及資料的儲存是一個重要的部分,希望引起注意!

五、參考資料
  • http://www.javascripture.com/ArrayBuffer
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array MDN Array
  • http://www.html5rocks.com/zh/tutorials/file/xhr2/ html5rocks
  • http://technet.microsoft.com/zh-cn/ie/br212485 MSDN

你所不知道的JavaScript數組

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.