Javascript의 배열은 강력한 기능을 제공합니다:
생성 시 길이를 지정할 수 없지만 동적으로 길이를 변경합니다. 일반 배열로 읽거나 스택으로 사용할 수 있습니다. 배열에 있는 각 요소의 값은 물론 유형까지 변경할 수 있습니다.
실제로는 객체입니다. 예를 들어 다음과 같은 배열을 만들 수 있습니다.
var array = new Array(10);
Javascript 배열의 강력함과 전능함은 우리에게 편리함을 가져다줍니다. 그러나 일반적으로:
만능인은 다양한 환경에서 사용될 수 있지만 모든 환경에 적합하지는 않습니다.
TypedArray는 Javascript에서 배열이 수행하는 "너무 많은 작업" 문제를 정확하게 해결하기 위해 등장했습니다.
원산지
TypedArray는 버퍼에서 바이너리 데이터를 읽을 수 있는 일반적인 고정 길이 버퍼 유형입니다.
Javascript가 바이너리 데이터를 처리하는 문제를 해결하기 위해 WEBGL 사양에 도입되었습니다.
TypedArray는 대부분의 최신 브라우저에서 지원됩니다. 예를 들어 다음 방법을 사용하여 TypedArray를 생성할 수 있습니다.
// 8바이트 ArrayBuffer 생성
var b = new ArrayBuffer(8);
// b에 대한 참조를 생성합니다. 유형은 Int32, 시작 위치는 0, 끝 위치는 버퍼의 끝
var v1 = new Int32Array(b);
// b에 대한 참조 생성, 유형은 Uint8, 시작 위치 2이고 끝 위치는 버퍼의 끝입니다
var v2 = new Uint8Array(b, 2);
// b에 대한 참조 생성, 유형은 Int16, 시작 위치는 2, 전체 길이는 2
var v3 = new Int16Array(b, 2 , 2);
그러면 버퍼링되고 생성된 참조 레이아웃은 다음과 같습니다.
变量 |
索引 |
|
字节数 |
b = |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
|
索引数 |
v1 = |
0 |
1 |
v2 = |
|
0 |
1 |
2 |
3 |
4 |
5 |
v3 = |
|
0 |
1 |
|
이는 Int32 유형의 v1 배열의 0번째 요소가 ArrayBuffer 유형의 b의 0-3바이트라는 의미입니다.
건축자
위에서는 ArrayBuffer를 통해 TypedArray를 생성했지만 실제로 TypedArray는 인스턴스를 생성하기 위해 3개의 생성자를 제공합니다.
|
생성자
TypedArray(unsigned long length)
새 TypedArray를 생성합니다. 길이는 고정 길이입니다.
TypedArray(TypedArray array)
TypedArray(type[] array)
새 TypedArray를 생성합니다. 각 요소는 배열에 따라 초기화되고 그에 따라 요소의 유형이 변환됩니다.
TypedArray(ArrayBuffer 버퍼, 선택적 unsigned long byteOffset, 선택적 unsigned long length)
버퍼에 대한 참조로 새 TypedArray를 생성합니다. byteOffset은 시작 오프셋이고 length는 길이입니다.
따라서 일반적으로 다음과 같은 방법으로 TypedArray를 만듭니다.
var array = new Uint8Array(10);
또는:
var array = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]);
데이터 운영
TypedArray는 데이터 작업을 위한 setter, getter, set 및 하위 배열의 네 가지 메서드를 제공합니다.
|
메소드 getter
type get(부호 없는 긴 인덱스)
지정된 인덱스에 있는 요소를 반환합니다.
setter void set(부호 없는 긴 인덱스,
유형 값)
지정된 인덱스의 요소를 지정된 값으로 설정합니다.
void
set(
TypedArray 배열, 선택적 부호 없는 긴 오프셋) void
set(
type[] 배열, 선택적 부호 없는 긴 오프셋)
배열에 따라 값을 설정하며, offset은 오프셋 위치입니다.
TypedArray 하위 배열(긴 시작, 선택적인 긴 끝)
시작 비트가 시작이고 끝 비트가 종료인 새 TypedArray를 반환합니다.
예를 들어 요소를 읽으려면 :
을 사용할 수 있습니다.
var array = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) 경고(배열[4]);
설정 요소를 사용할 수 있습니다 :
var array = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) Alert(array[4]); //5array[4] = 12;alert(array[ 4]); //12
을 사용하여 사본 받기:
var array = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) var array2 = array.subarray(0);
|
유형
类型 |
大小 |
描述 |
Web IDL类型 |
C 类型 |
Int8Array |
1 |
8位有符号整数 |
byte |
signed char |
Uint8Array |
1 |
8位无符号整数 |
octet |
unsigned char |
Uint8ClampedArray |
1 |
8位无符号整数 (clamped) |
octet |
unsigned char |
Int16Array |
2 |
16位有符号整数 |
short |
short |
Uint16Array |
2 |
16位无符号整数 |
unsigned short |
unsigned short |
Int32Array |
4 |
32位有符号整数 |
long |
int |
Uint32Array |
4 |
32位无符号整数 |
unsigned long |
unsigned int |
Float32Array |
4 |
32位IEEE浮点数 |
unrestricted float |
float |
Float64Array |
8 |
64位IEEE浮点数 |
unrestricted double |
double |
사이즈
설명
웹 IDL 유형
C타입
Int8Array |
1 |
8비트 부호 있는 정수 |
바이트 |
부호 있는 문자 |
Uint8Array |
1 |
8비트 부호 없는 정수 |
옥텟 |
부호 없는 문자 |
Uint8ClampedArray |
1 |
8비트 부호 없는 정수(클램핑됨) |
옥텟 |
부호 없는 문자 |
Int16Array |
2 |
16비트 부호 있는 정수 |
짧게 |
짧게 |
Uint16Array |
2 |
16비트 부호 없는 정수 |
부호 없는 짧은 |
부호 없는 짧은 |
Int32Array |
4 |
32비트 부호 있는 정수 |
긴 |
정수 |
Uint32Array |
4 |
32비트 부호 없는 정수 |
부호 없는 긴 |
부호 없는 정수 |
Float32Array |
4 |
32비트 IEEE 부동 소수점 수 |
무제한 부동 소수점 |
부동 |
Float64Array |
8 |
64비트 IEEE 부동 소수점 수 |
무제한 이중 |
더블 |
캔버스를 가지고 놀아보신 분들이라면 익숙하실 겁니다.
ImageData에 이미지 데이터를 저장하는 데 사용되는 배열이 Uint8ClampedArray 유형이기 때문입니다.
예:
var context = document.createElement("canvas").getContext("2d");var imageData = context.createImageData(100, 100);console.log(imageData.data);
FireBug에서
로 표시되는 :
Uint8ClampedArray { 0=0, 1=0, 2=0, 기타...}
TypedArray를 사용하는 이유
우리는 Javascript의 숫자가 64비트 부동 소수점 숫자라는 것을 알고 있습니다. 바이너리 이미지(이미지의 각 픽셀은 8비트 부호 없는 정수로 저장됨)의 경우 해당 데이터를 Javascript 배열에서 사용하려는 경우 이미지 메모리의 8배를 사용하여 데이터를 저장하는 것과 같습니다. 이것은 분명히 비과학적인 이미지입니다. TypedArray를 사용하면 원래 메모리의 1/8만 사용하여 이미지 데이터를 저장할 수 있습니다.
또는 WebSocket의 경우 base64를 사용하여 전송하는 것도 비용이 많이 드는 방법이며, 바이너리 전송으로 전환하는 것이 더 나은 방법일 수 있습니다.
물론 TypedArray에는 더 나은 성능과 같은 더 많은 이점이 있습니다. 아래에서는 이를 확인하기 위해 몇 가지 작은 테스트를 수행합니다.
테스트에 참여한 브라우저는 :
FireFox 17.0.1 및 Chrome 23.0.1271.97m
테스트1: 순차 읽기 속도 읽기
var timeArray1 = [];
var timeArray2 = [];
function check1(){
var array = new Uint8ClampedArray(5000000);
for(var i = array.length; i- -;){
array[i] = Math.floor(Math.random() * 100);
}
var temp;
var time1 = (new Date()). getTime( );
for(var i = array.length; i--;){
temp = array[i];
}
var time2 = (new Date()).getTime () ;
console.log(time2 - time1);
timeArray1.push(time2 - time1);
}
function check2(){
var array2 = new Array(5000000) ;
for(var i = array2.length; i--;){
array2[i] = Math.floor(Math.random() * 100);
}
var temp;
var time3 = (new Date()).getTime();
for(var i = array2.length; i--;){
temp = array2[i];
}
var time4 = (new Date()).getTime();
console.log(time4 - time3);
timeArray2.push(time4 - time3);
}
함수 타이머( __fun, __time, __callback){
var now = 0;
function start(){
var timeout = setTimeout(function(){
if(now !== __time){
이제
__fun();
start();
}else{
if(timeArray1.length && timeArray2.length){
console.log("timeArray1 == " timeArray1 " ,average == "average(timeArray1));
console.log("timeArray2 == "timeArray2",average == "average(timeArray2));
}
__callback && __callback();
}
}, 100);
}
start();
}
functionaverage(__array){
var total = 0;
for(var i = __array .length; i--;){
total = __array[i];
}
return (total / __array.length);
}
timer(check1, 10, 함수( ){
타이머(check2, 10);
});
Uint8ClampedArray의 읽기 속도가 Array보다 확실히 빠른 것을 볼 수 있습니다(바가 길수록 시간이 더 많이 걸립니다).
테스트2: 무작위 읽기
//……
function check1(){
var array = new Uint8ClampedArray(5000000);
for(var i = array.length; i--;){
array[i] = Math.floor(Math.random() * 100);
}
var temp;
var time1 = (new Date()).getTime();
for (var i = array.length; i--;){
temp = array[Math.floor(Math.random() * 5000000)];
}
var time2 = (new Date() ).getTime();
console.log(time2 - time1);
timeArray1.push(time2 - time1);
}
function check2(){
var array2 = 새 배열 (5000000);
for(var i = array2.length; i--;){
array2[i] = Math.floor(Math.random() * 100);
}
var temp;
var time3 = (new Date()).getTime();
for(var i = array2.length; i--;){
temp = array2[Math.floor(Math .random() * 5000000)];
}
var time4 = (new Date()).getTime();
console.log(time4 - time3);
timeArray2.push(time4 - 시간3);
}
//……
随即读取中Uint8ClampedArray를 사용하여 Array를 변경할 수 있습니다.
테스트3:顺序写入
//……
function check1(){
var array = new Uint8ClampedArray(5000000);
var time1 = (new Date()).getTime();
for(var i = array.length; i--;){
array[i] = Math.floor(Math.random() * 100);
}
var time2 = (new Date()).getTime ();
console.log(time2 - time1);
timeArray1.push(time2 - time1);
}
function check2(){
var array2 = new Array(5000000) ;
var time3 = (new Date()).getTime();
for(var i = array2.length; i--;){
array2[i] = Math.floor(Math. 무작위() * 100);
}
var time4 = (new Date()).getTime();
console.log(time4 - time3);
timeArray2.push(time4 - time3 );
}
//……
테스트4: 复제조작업(U8C에서 U8C로, 배열에서 U8C로)
//……
기능 확인1 (){
var array = new Uint8ClampedArray(5000000);
for(var i = array.length; i--;){
array[i] = Math.floor(Math.random() * 100);
}
var temp;
var array2 = new Uint8ClampedArray(5000000);
var time1 = (new Date()).getTime();
array2.set( array);
var time2 = (new Date()).getTime();
console.log(time2 - time1);
timeArray2.push(time2 - time1);
}
function check2(){
var array = new Array(5000000);
for(var i = array.length; i--;){
array[i] = Math.floor(Math. 무작위() * 100);
}
var temp;
var array2 = new Uint8ClampedArray(5000000);
var time1 = (new Date()).getTime();
array2 .set(array);
var time2 = (new Date()).getTime();
console.log(time2 - time1);
timeArray2.push(time2 - time1);
}
//…