JS 的學習往往最常用的是在電子商務 WordPress 網站建設中,JS 除了基本資料型別,陣列就是資料組合,當然肯定還會有在我們電子商務 WordPress 網站建設中我們沒有學習或者很少學習到的陣列,下面我們就來講講電子商務 WordPress 網站建設學習中 JS 陣列問題。

 

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

 

  一、 Array 在記憶體中的堆疊模型

 

  1. Array 的獲取

 

  Javascript 中如何產生 Array:

 

  JavaScript

 

  [element0, element1, …, elementN]

 

  new Array(element0, element1, …, elementN)

 

  new Array(arrayLength)

 

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

 

  JavaScript

 

  ”array”.split(“”);

 

  ”array”.match(/a|r/g);

 

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

 

  2. 堆疊模型

 

  在陣列中我們可以放很多不同資料型別的資料,如:

 

  JavaScript

 

  var arr = [21, “ 李靖”, new Date(), function(){}, , null];

 

  上面這個陣列中一次放入了 數字、字串、物件、函式、 undefined 和 null,對於上面的資料介面我們可以具象的描述下:

 

  JavaScript

 

  棧

 

  +———+ 堆

 

  | 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 這個建構函式可以建立一個原始緩衝區:

 

  JavaScript

 

  var buffer = new ArrayBuffer(30);

 

  從 chrome 控制枱可以看到:

 

  

 

 

  buffer 例項擁有一個 byteLength 的屬性,用於獲取 buffer 的 size,一個只有 IE11+ 以及 ios6+ 支援的 slice 方法,用於對 buffer 長度進行擷取操作。

 

  JavaScript

 

  ArrayBuffer slice(

 

  unsigned long begin

 

  unsigned long end Optional

 

  );

 

  可以測試這個 DEMO:

 

  JavaScript

 

  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 物件 的各種檢視。 所有陣列型別的長度均固定。

 

  Int 就是整型,Uint 為無符號整形,Float 為浮點型,這些是 C 語言中的基本概念,我就不具體解釋了。由於這些檢視化結構都是大同小異,本文只對 Float32Array 型別作説明,讀者可以舉一反三。

 

  Float32Array 跟 Array 是十分類似的,只不過他每一個元素都是都是一個 32 位 (4 字節) 的浮點型資料。 Float32Array 一旦建立其大小不能再修改。

 

  我們可以直接建立一個 Float32Array:

 

  JavaScript

 

  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 位的資料型別,再如:

 

  JavaScript

 

  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 位浮點數。

 

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

 

  JavaScript

 

  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] 並沒有變化。

 

  除了上面的方式,我們還可以通過其他方式來建立一個型別化陣列:

 

  JavaScript

 

  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.

 

  JavaScript

 

  ArrayBuffer(12)

 

  +-+-+-+-+-+-+-+-+-+-+-+-+-+

 

  |0|1|2|3|4|5|6|7|8| | | | |

 

  +-+-+-+-+-+-+-+-+-+-+-+-+-+

 

   /

 

  x (Float32Array)

 

  offset:0

 

  byteLength:4

 

  length:2

 

  JavaScript

 

  ArrayBuffer(12)

 

  +-+-+-+-+-+-+-+-+-+-+-+-+-+

 

  |0|1|2|3|4|5|6|7|8| | | | |

 

  +-+-+-+-+-+-+-+-+-+-+-+-+-+

 

   /

 

  y

 

  Created By Barret Lee

 

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

 

  3. DataView 物件

 

  DataView 物件對資料的操作更加細緻,不過我覺得沒啥意思,上面提到的各種型別化陣列已經可以基本滿足應用了,所以這裏就一筆帶過,一個簡單的示例:

 

  JavaScript

 

  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

 

  三、 XHR2 中的 ArrayBuffer

 

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

 

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

 

  請求 響應

 

  text DOMString

 

  arraybuffer ArrayBuffer

 

  blob Blob

 

  document Document

 

  舉個栗子:

 

  JavaScript

 

  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,那麼在拿到的資料中就可以用型別化陣列來接受啦。

 

  JS 不是那麼容易學習的,尤其是自己通過學習來搭建電子商務 WordPress 網站更是非常困難,上述簡單介紹了一下 JS 陣列。