JavaScript 형식화 배열(typed array)은 배열같은 객체이고 원시(raw) 이진 데이터에 액세스하기 위한 메커니즘을 제공합니다. 이미 아시다시피, Array
객체는 동적으로 늘었다 줄고 어떤 JavaScript 값이든 가질 수 있습니다. JavaScript 엔진은 이러한 배열이 빨라지도록 최적화를 수행합니다. 그러나, audio 및 video 조작과 같은 기능 추가, WebSocket을 사용한 원시 데이터에 액세스 등 웹 어플리케이션이 점점 더 강력해짐에 따라, 빠르고 쉽게 형식화 배열의 원시 이진 데이터를 조작할 수 있게 하는 것이 JavaScript 코드에 도움이 될 때가 있음이 분명해 졌습니다.
그러나, 형식화 배열은 보통 배열과 혼동되지는 않습니다, 형식화 배열에 Array.isArray()
호출은 false
를 반환하기에. 게다가, 보통 배열에 이용할 수 있는 모든 메서드가 형식화 배열에 의해 지원되지는 않습니다(가령 push 및 pop).
버퍼 및 뷰: 형식화 배열 구조
최대 유연성 및 효율을 달성하기 위해, JavaScript 형식화 배열은 구현을 버퍼 및 뷰로 나눕니다. 버퍼 (ArrayBuffer
객체에 의해 구현됨)는 데이터 부분(chunk, 덩어리)을 나타내는 객체입니다; 이야기 할 형식이 없으며, 그 콘텐츠에 액세스하기 위한 메커니즘을 제공하지 않습니다. 버퍼에 포함된 메모리에 액세스하기 위해, 뷰를 사용할 필요가 있습니다. 뷰는 문맥(context, 즉 데이터 형, 시작 오프셋 및 요소 수)을 제공해 데이터를 실제 형식화 배열로 바꿉니다.
ArrayBuffer
ArrayBuffer
는 일반 고정 길이 이진 데이터 버퍼를 나타내는 데 사용되는 데이터 형입니다. ArrayBuffer
콘텐츠를 직접 조작할 수는 없습니다; 대신에, 형식화 배열 뷰 또는 특정 형식으로 버퍼를 나타내는 DataView
를 만들어 버퍼의 콘텐츠를 읽고 쓰기 위해 사용합니다.
형식화 배열 뷰
형식화 배열 뷰는 자체 설명형 이름이 있으며 Int8
, Uint32
, Float64
등과 같은 모든 일반 숫자 형을 위한 뷰를 제공합니다. 특별한 형식화 배열 뷰가 하나 있습니다, Uint8ClampedArray
. 값은 0에서 255 사이로 단속(제한)합니다. 예를 들어, 이는 Canvas 데이터 처리에 유용합니다.
유형 | 크기 (바이트) | 설명 | Web IDL 형 | 해당 C 형 |
Int8Array |
1 | 8비트 2의 보수 형식 부호 있는 정수 | byte |
int8_t |
Uint8Array |
1 | 8비트 부호 없는 정수 | octet |
uint8_t |
Uint8ClampedArray |
1 | 8비트 부호 없는 정수 (단속됨) | octet |
uint8_t |
Int16Array |
2 | 16비트 2의 보수 형식 부호 있는 정수 | short |
int16_t |
Uint16Array |
2 | 16비트 부호 없는 정수 | unsigned short |
uint16_t |
Int32Array |
4 | 32비트 2의 보수 형식 부호 있는 정수 | long |
int32_t |
Uint32Array |
4 | 32비트 부호 없는 정수 | unsigned long |
uint32_t |
Float32Array |
4 | 32비트 IEEE 부동 소수점 수 | unrestricted float |
float |
Float64Array |
8 | 64비트 IEEE 부동 소수점 수 | unrestricted double |
double |
DataView
DataView
는 버퍼에 임의 데이터를 읽고 쓰기 위해 getter/setter API를 제공하는 저레벨 인터페이스입니다. 예를 들어, 서로 다른 유형의 데이터를 처리하는 경우 유용합니다. 형식화 배열 뷰는 플랫폼의 본디(native) 바이트 순서(byte-order, Endianness 참조)에 속합니다. DataView
로 바이트 순서를 제어할 수 있습니다. 기본으로 big-endian이고 getter/setter 메서드로 little-endian으로 설정될 수 있습니다.
형식화 배열을 사용하는 웹 API
FileReader.prototype.readAsArrayBuffer()
FileReader.prototype.readAsArrayBuffer()
메서드는 지정된Blob
또는File
의 콘텐츠를 읽기 시작합니다.XMLHttpRequest.prototype.send()
XMLHttpRequest
인스턴스의send()
메서드는 이제 형식화 배열 및 인수로ArrayBuffer
객체를 지원합니다.ImageData.data
0
에서255
까지 정수값으로 RGBA 순 데이터를 포함하는 1차원 배열을 나타내는Uint8ClampedArray
입니다.
예
버퍼와 뷰 사용하기
우선, 여기서 16바이트 고정 길이로 버퍼를 만들어야 합니다:
var buffer = new ArrayBuffer(16);
이 시점에서, 바이트가 모두 0으로 미리 초기화된 메모리 덩어리가 있습니다. 그렇지만 이거 가지고 할 수 있는 게 많지 않습니다. 실제 16바이트 길이인지 확인할 수 있고 대략 그런 정도입니다:
if (buffer.byteLength === 16) { console.log("Yes, it's 16 bytes."); } else { console.log("Oh no, it's the wrong size!"); }
정말 이 버퍼로 작업할 수 있기 전에, 뷰를 만들어야 합니다. 32비트 부호있는 정수 배열로 버퍼의 데이터를 다루는 뷰를 만듭시다:
var int32View = new Int32Array(buffer);
이제 보통 배열처럼 배열 내 필드에 액세스할 수 있습니다:
for (var i = 0; i < int32View.length; i++) { int32View[i] = i * 2; }
이는 배열의 4항목을 값 0, 2, 4 및 6으로 채웁니다 (4항목이 각각 4바이트에 총 16바이트가 됩니다).
같은 데이터에 여러 뷰
상황은 당신이 같은 데이터에 여러 뷰를 만들 수 있음을 고려하는 경우 정말 흥미로워지기 시작합니다. 예를 들어, 위 코드가 주어지면 다음과 같이 계속할 수 있습니다:
var int16View = new Int16Array(buffer); for (var i = 0; i < int16View.length; i++) { console.log("Entry " + i + ": " + int16View[i]); }
여기서 우리는 기존 32비트 뷰와 같은 버퍼를 공유하는 16비트 정수 뷰를 만들고 16비트 정수로 버퍼 내 모든 값을 출력합니다. 이제 우리는 출력 0, 0, 2, 0, 4, 0, 6, 0을 얻습니다.
그렇지만 한 단계 더 앞으로 갈 수 있습니다. 다음을 생각해 보세요:
int16View[0] = 32; console.log("Entry 0 in the 32-bit array is now " + int32View[0]);
이로부터 출력은 "Entry 0 in the 32-bit array is now 32"입니다. 즉, 두 배열은 확실히 그저 같은 데이터 버퍼 상의 뷰입니다, 버퍼를 서로 다른 형식으로 다루는. 모든 뷰 유형으로 이를 할 수 있습니다.
복잡한 데이터 구조(체)와 작업하기
단일 버퍼를 서로 다른 형인 여러 뷰(버퍼 내 서로 다른 오프셋에서 시작하는)와 결합시켜, 여러 데이터 형을 포함하는 데이터 객체와 상호 작용할 수 있습니다. 예를 들어, 이는 WebGL, 데이터 파일 또는 js-ctypes를 쓰는 동안 사용해야 하는 C 구조체에서 복잡한 데이터 구조와 상호 작용케 합니다.
이 C 구조체를 생각해 보세요:
struct someStruct { unsigned long id; char username[16]; float amountDue; };
이 같은 형식으로 데이터를 포함하는 버퍼에 액세스할 수 있습니다:
var buffer = new ArrayBuffer(24); // ... 버퍼 내의 데이터를 읽어들임 ... var idView = new Uint32Array(buffer, 0, 1); var usernameView = new Uint8Array(buffer, 4, 16); var amountDueView = new Float32Array(buffer, 20, 1);
그런 뒤, 예를 들어 amountDueView[0]
로 지불할 요금(amount due)을 액세스할 수 있습니다.
보통 배열로 변환
형식화 배열을 처리한 뒤, 때때로 Array
프로토타입의 도움을 받기 위해 보통 배열로 다시 변환하는 게 유용합니다. 이는 Array.from
또는 Array.from
이 지원되지 않는 경우 다음 코드를 사용하여 수행할 수 있습니다.
var typedArray = new Uint8Array([1, 2, 3, 4]), normalArray = Array.prototype.slice.call(typedArray); normalArray.length === 4; normalArray.constructor === Array;
스펙
스펙 | 상태 | 설명 |
---|---|---|
Typed Array Specification | Obsolete | ECMAScript 6로 대체됨. |
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'TypedArray Objects' in that specification. |
Standard | ECMA 표준에서 초기 정의. |
ECMAScript 2017 Draft (ECMA-262) The definition of 'TypedArray Objects' in that specification. |
Draft |
브라우저 호환성
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | 7.0 | 4.0 (2) | 10 | 11.6 | 5.1 |
Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Basic support | 4.0 | (Yes) | 4.0 (2) | 10 | 11.6 | 4.2 |