Javascript 操作二進(jìn)制數(shù)據(jù)

一個(gè)類型化數(shù)組(TypedArray)對(duì)象描述了一個(gè)底層的二進(jìn)制數(shù)據(jù)緩沖區(qū)(binary data buffer)的一個(gè)類數(shù)組視圖(view)。事實(shí)上,沒(méi)有名為 TypedArray 的全局屬性,也沒(méi)有一個(gè)名為 TypedArray 的構(gòu)造函數(shù)。相反,有許多不同的全局屬性,它們的值是特定元素類型的類型化數(shù)組構(gòu)造函數(shù)。
TypedArray 指的是以下的其中之一
Int8Array();Uint8Array();Uint8ClampedArray();Int16Array();Uint16Array();Int32Array();Uint32Array();Float32Array();Float64Array();
描述
ECMAScript 2015 定義了一個(gè) TypeArray 構(gòu)造器作為所有的類型化數(shù)組構(gòu)造器(Int8Array, Int16Array 等)的原型([[Prototype]])。該構(gòu)造器并不會(huì)直接暴露出來(lái):即沒(méi)有全局的 %TypedArray% 和 TypeArray 屬性,只能通過(guò)使用類似于 Object.getPrototypeOf(Int8Array.prototype) 的方式直接訪問(wèn)。所有的類型化數(shù)組構(gòu)造器都會(huì)繼承 %TypeArray% 構(gòu)造器函數(shù)的公共屬性和方法。此外,所有的類型化數(shù)組的原型(如 Int8Array.prototype)都以 %TypeArray%.prototype 作為原型。
%TypedArray% 構(gòu)造器自身不是特別有用,直接調(diào)用或使用 new 表達(dá)式實(shí)例化都會(huì)拋出一個(gè)TypeError 異常,除非在支持子類化(subclassing)創(chuàng)建對(duì)象的 JS 引擎下運(yùn)行。但直到現(xiàn)在還沒(méi)有這樣的 JS 引擎出現(xiàn)。因此 %TypeArray% 僅僅在對(duì)所有的類型化數(shù)組構(gòu)造器(Int8Array 等)的方法和屬性進(jìn)行 polyfill 的時(shí)候比較有用.
當(dāng)創(chuàng)建一個(gè) TypedArray 實(shí)例(如 Int8Array)時(shí),一個(gè)數(shù)組緩沖區(qū)將被創(chuàng)建在內(nèi)存中,如果一個(gè) ArrayBuffer 對(duì)象被當(dāng)作參數(shù)傳給構(gòu)造函數(shù),那么將使用傳入的 ArrayBuffer 代替(即緩沖區(qū)被創(chuàng)建到 ArrayBuffer 中)。緩沖區(qū)的地址被存儲(chǔ)在實(shí)例的內(nèi)部屬性中,并且所有 %TypedArray%.prototype上的方法,例如 set value 和 get value 等,都會(huì)在這個(gè)數(shù)組緩沖區(qū)上進(jìn)行操作。
屬性訪問(wèn)
你可以使用標(biāo)準(zhǔn)數(shù)組索引語(yǔ)法獲取類型化數(shù)組中的元素(也就是和訪問(wèn)普通數(shù)組元素一樣,如?foo[1]),然而,在類型化數(shù)組上獲取或者設(shè)置屬性的值時(shí),并不會(huì)在這個(gè)屬性的原型鏈中進(jìn)行搜索,即使在索引超出了邊界的時(shí)候。在原型中添加的屬性將會(huì)在 ArrayBuffer 中查詢而不是在對(duì)象的屬性中。但是你依然可以像其他對(duì)象一樣使用命名的屬性來(lái)訪問(wèn)(foo.bar 的形式);具體見(jiàn)下面的例子:
// 使用標(biāo)準(zhǔn)數(shù)組語(yǔ)法來(lái)獲取和設(shè)置屬性值var int16 = new Int16Array(2);int16[0] = 42;console.log(int16[0]); // 42// 原型中添加的屬性訪問(wèn)不到(此時(shí)索引值未超邊界,20 < 32)Int8Array.prototype[20] = "foo";(new Int8Array(32))[20]; // 0// 即使索引值超出了邊界也一樣不能訪問(wèn)(20 > 8)Int8Array.prototype[20] = "foo";(new Int8Array(8))[20]; // undefined// 使用負(fù)數(shù)索引也不行Int8Array.prototype[-1] = "foo";(new Int8Array(8))[-1]; // undefined// 但是可以使用命名屬性的方式訪問(wèn)到Int8Array.prototype.foo = "bar";(new Int8Array(32)).foo; // "bar"
總結(jié)
ArrayBuffer 對(duì)象用來(lái)表示通用的、固定長(zhǎng)度的原始二進(jìn)制數(shù)據(jù)緩沖區(qū)。它是一個(gè)字節(jié)數(shù)組,通常在其他語(yǔ)言中稱為“byte array”。
const buffer = new ArrayBuffer(8);console.log(buffer.byteLength);// expected output: 8
你不能直接操作 ArrayBuffer 的內(nèi)容,而是要通過(guò)類型數(shù)組對(duì)象或 DataView 對(duì)象來(lái)操作,它們會(huì)將緩沖區(qū)中的數(shù)據(jù)表示為特定的格式,并通過(guò)這些格式來(lái)讀寫緩沖區(qū)的內(nèi)容。
const buffer = new ArrayBuffer(8);const view = new Int32Array(buffer);
類型化數(shù)組是 Javascript 操作(內(nèi)存)二進(jìn)制數(shù)據(jù)的一個(gè)接口。類型化數(shù)組是建立在 ArrayBuffer 對(duì)象的基礎(chǔ)上的。它的作用是,分配一段可以存放數(shù)據(jù)的連續(xù)內(nèi)存區(qū)域。ArrayBuffer 作為內(nèi)存區(qū)域,可以存放多種類型的數(shù)據(jù)。不同數(shù)據(jù)有不同的存儲(chǔ)方式,這就叫做“視圖”。目前,JavaScript 提供以下類型的視圖。

