本篇文章帶大家來將一下JavaScript中的類型化數(shù)組,看看它的組成、與普通數(shù)組不同,以及在Web開發(fā)中的用途。
在 JavaScript 這門語言中,我們所有人都必須對數(shù)組足夠熟悉,知曉數(shù)組本質(zhì)上是動態(tài)的,并且可以容納任何 JavaScript 對象。不過,如果你曾經(jīng)使用過類似于 C 語言這樣的其他語言,你應(yīng)該知道其數(shù)組本質(zhì)上不是動態(tài)的。而且你只能在該數(shù)組中存儲特定的數(shù)據(jù)類型,畢竟從性能角度來看,這可以確保數(shù)組效率更高。但數(shù)組的動態(tài)化與存儲信息類型的多樣化其實(shí)并沒有使 JavaScript 數(shù)組效率低下。在 JavaScript 引擎優(yōu)化的幫助下,JavaScript 中數(shù)組的執(zhí)行速度其實(shí)非??臁?/p>
隨著 Web 應(yīng)用程序功能越來越強(qiáng)大,我們開始需要讓 Web 應(yīng)用程序處理和操縱原始二進(jìn)制數(shù)據(jù)。JavaScript 數(shù)組無法處理這些原始二進(jìn)制數(shù)據(jù),也因此我們引入了 JavaScript 的類型化數(shù)組。
類型化數(shù)組
類型化數(shù)組是與數(shù)組非常相似的對象,但是它提供了一種將原始二進(jìn)制數(shù)據(jù)寫入內(nèi)存緩沖區(qū)的機(jī)制。所有主要瀏覽器均很好地支持此功能,并且 ES6 已將其集成到 JavaScript 核心框架中,也可以訪問諸如 map()
、filter()
等 Array 方法。我強(qiáng)烈建議你瀏覽本文結(jié)尾處提到的資源,以更深入了解類型化數(shù)組。
組成
類型化數(shù)組由兩個主要部分組成,Buffer
和 View
。
緩沖區(qū)
Buffer
是 ArrayBuffer
類型的對象,表示一個數(shù)據(jù)塊。此原始二進(jìn)制數(shù)據(jù)塊無法被單獨(dú)訪問或修改。你可能好奇,無法訪問或修改的數(shù)據(jù)對象的能有什么用途。實(shí)際上視圖是緩沖區(qū)的讀寫接口。
視圖
View
是一個對象,允許你訪問和修改存儲在 ArrayBuffer
中的原始二進(jìn)制內(nèi)容。一般來說有兩種視圖。
TypedArray
對象的實(shí)例
這些類型的對象與普通數(shù)組非常相似,但是僅存儲單一類型的數(shù)值數(shù)據(jù)。諸如 Int8
、Uint8
、Int16
、Float32
就是類型化數(shù)組的數(shù)據(jù)類型。類型中的數(shù)字表示為數(shù)據(jù)類型分配的位數(shù)。例如,Int8
表示 8 位的整數(shù)。
你可以閱讀 參考文檔 來詳細(xì)了解類型化數(shù)組的數(shù)據(jù)類型。
DataView
對象的實(shí)例
DataView
是一個低級接口,提供了一個 getter
/ setter
API 來讀取和寫入任意數(shù)據(jù)到緩沖區(qū)。這很大程度上方便了我們的開發(fā),尤其是需要在單個類型化數(shù)組中處理多種數(shù)據(jù)類型時。
使用 DataView
的另一個好處是,它可以讓你控制數(shù)據(jù)的字節(jié)序 —— 類型化數(shù)組使用平臺的字節(jié)序。當(dāng)然如果你的程序運(yùn)行在本地,這將不是問題,因?yàn)槟愕脑O(shè)備將使用與輸入數(shù)組相同的字節(jié)序。在大多數(shù)情況下,你的類型化數(shù)組將為低端字節(jié)序,因?yàn)橛⑻貭柌扇〉氖切《俗止?jié)序。由于英特爾在計(jì)算機(jī)處理器中非常普遍,因此大多數(shù)時候不會出現(xiàn)問題。但是,如果將小端字節(jié)序編碼的數(shù)據(jù)傳輸?shù)绞褂么蠖俗止?jié)序編碼的設(shè)備,則會導(dǎo)致讀取時候的錯誤,最終可能導(dǎo)致數(shù)據(jù)的丟失。由于 DataView
使你可以控制字節(jié)序的方向,因此你可以在必要時使用它。
是什么使它們與普通數(shù)組不同
如前所述,普通的 JavaScript 數(shù)組已通過 JavaScript 引擎進(jìn)行了優(yōu)化,你沒必要為了提升性能而使用類型化數(shù)組,因?yàn)檫@不會給你帶來太多升級。但是有些特性使類型化數(shù)組不同于普通數(shù)組,這才可能是你選擇它們的原因。
- 讓你能夠處理原始二進(jìn)制數(shù)據(jù)
- 由于它們處理的數(shù)據(jù)類型是有限的,因此與普通數(shù)組相比,你的引擎更易優(yōu)化類型化數(shù)組,因?yàn)槠胀〝?shù)組的優(yōu)化其實(shí)是一個非常復(fù)雜的過程。
- 不能保證普通數(shù)組永遠(yuǎn)都能得到優(yōu)化,因?yàn)槟愕囊婵赡芤蚋鞣N原因決定不進(jìn)行優(yōu)化。
在 Web 開發(fā)中的用途
XMLHttpRequest API
你可以根據(jù)你的響應(yīng)類型以 ArrayBuffer
形式接收數(shù)據(jù)響應(yīng)。
const xhr = new XMLHttpRequest(); xhr.open('GET', exampleUrl); xhr.responseType = 'arraybuffer'; xhr.onload = function () { const arrayBuffer = xhr.response; // 處理數(shù)據(jù) }; xhr.send();
Fetch API
類似于 XMLHttpRequest API,F(xiàn)etch API 還允許你在 ArrayBuffer
中接收響應(yīng)。你只需在 fetch API 響應(yīng)中使用 arrayBuffer()
方法,你就能夠收到一個使用 ArrayBuffer
解析的 Promise
。
fetch(url) .then(response => response.arrayBuffer()) .then(arrayBuffer => { // 處理數(shù)據(jù) });
HTML Canvas
HTML5 Canvas 元素使你可以渲染動態(tài)的 2D 形狀和位圖圖像。該元素僅充當(dāng)圖形的容器,而圖形則是在 JavaScript 的幫助下繪制。
canvas 的 2D Context 使你可以將位圖數(shù)據(jù)作為 Uint8ClampedArray
的實(shí)例進(jìn)行檢索。讓我們看一下 Axel 博士提供的示例代碼:
const canvas = document.getElementById('my_canvas'); const context = canvas.getContext('2d'); const imageData = context.getImageData(0, 0, canvas.width, canvas.height); const uint8ClampedArray = imageData.data;
WebGL
WebGL 允許你渲染高性能的交互式 3D 和 2D 圖形。它在很大程度上依賴于類型化數(shù)組,因?yàn)樗鼤幚碓枷袼財(cái)?shù)據(jù)以在畫布上輸出必要的圖形。
你可以在 這篇文章 中閱讀有關(guān) WebGL 基礎(chǔ)的