최근 자바스크립트에대해서 공부를 하고있는데 배열에대해서 공부한 내용을 정리해보려고 한다.

자바스크립트 배열의 특징

  1. 자바스크립트 배열은 번호가 메겨진 인덱스를 갖는 특별한 유형의 객체이다.
    • 자바스크립트의 배열은 다른 언어의 배열과 유사한 “객체”이다.
      (index를 key로 가지며 length를 갖는 특수 객체)
  2. 배열에 여러 다른 유형의 변수, 오브젝트, 함수를 요소로 가질 수 있다.
    • (js는 함수를 객체로 취급하기 때문)
  3. 다른 언어의 배열(밀집배열)과는 다르게 메모리가 연속적으로 이어져 있지 않음(희소배열)

자바스크립트 배열의 장점

  • 배열의 요소를 위한 메모리 공간이 동일한 크기를 갖지 않아도 됨.
  • 그렇기 때문에 다양한 요소를 배열 내에 넣을 수 있음
  • 요소를 삽입 삭제하는 경우에는 일반적인 배열보다 빠른 성능

 

 

자바스크립트 배열의 단점

  • 연속되지 않은 메모리로 인하여 다른 언어의 배열에 비하여 배열 요소 참조에 대한 속도가 느림

 

 

V8엔진에서의 배열

V8엔진을 비롯한 최신 자바스크립트 엔진에서는 위의 단점을 극복하기 위하여 희소배열과 밀집배열을 모두 지원하며 상황에 맞는 배열이 자동으로 사용됨

0번째 인덱스부터 순서대로 시작하는 키 값 을 사용하는 배열을 생성하는 경우 엔진은 배열의 각 요소를 선형 저장 버퍼 형태(밀집배열)로 저장함.

예) array = [1,2,3] 

위처럼 중간이 비어 있는 형태의의 배열을 생성하거나 배열의 요소를 삭제할 경우 배열의 형태는
해시 테이블 형태로(희소배열) 생성, 변경된다.

예)
const array = []; 
array[0] = 1; 
array[1] = 2; 
array[3] = 3;

성능면에서 밀집배열이 희소배열보다 성능이 뛰어나기 때문에

가능하다면 밀집배열의 형태로 배열을 사용하는것이 좋다.

 

 

자바스크립트 배열의 성능을 올리기 위해서는(밀집배열을 사용하기 위해서는)

  1. 인덱스가 0부터 시작되는 연속된 키 값을 사용하는 배열을 만든다.
  2. 배열의 크기를 미리 선언하지 않는다.
  3. 배열의 요소를 삭제하지 않는다.

 

 

자바스크립트 배열 선언방법

  1. 리터럴
    var arr = []; arr[0]; undefined
    var arr = [1, 2]; arr[0]; 1
    var arr = [5, "three", 1]; arr[0]; 5
  2. 객체
    var arr = new Array(); arr[0]; undefined
    var arr = new Array(3); arr[0]; undefined
    var arr = new Array(1, 2, 3, 4, 5); arr[0]; 1

객체 선언방법 사용 시 Array(3); 형태로 선언 할 경우

Length가 3인 배열이 생성되는 등 사용방법에 혼동이 발생할 수 있음
특별한 이유가 없다면 리터럴 형태로 배열을 사용하는것이 좋다.

 

 

선언방식별 속도 비교

console.time('using[]')
for(var i=0; i<2000000; i++){var arr = []};
console.timeEnd('using[]')

console.time('using new')
for(var i=0; i<2000000; i++){var arr = new Array()} 
console.timeEnd('using new')

일반적으로 new Array로 배열을 생성하는 것이 시간이 더 오래 걸리는 것을 확인

  • 이유 :
    배열을 리터럴 방식으로 생성할 경우 자바스크립트 컴파일러 시점에서 [] 문자를 읽자마자 이미 배열을 생성하겠다는 것이 명확함
    반대로 new Array 의 경우 더 많은 단어로 이루어져 있으며 new 문자열을 읽고 이후 Array 문자열을 읽은 후 배열을 생성하겠다는 것이 명확해짐

또한 각 선언방식을 해석하면 아래와 같이 분석할 수 있는데

[]: ARRAY_INIT
[1]: ARRAY_INIT (NUMBER)
[1, foo]: ARRAY_INIT (NUMBER, IDENTIFIER)
new Array: NEW, IDENTIFIER
new Array(): NEW, IDENTIFIER, CALL
new Array(5): NEW, IDENTIFIER, CALL (NUMBER)
new Array(5,4): NEW, IDENTIFIER, CALL (NUMBER, NUMBER)
new Array(5, foo): NEW, IDENTIFIER, CALL (NUMBER, IDENTIFIER)

Array 라는 문자열은 IDENTIFIER 즉 식별자로써 분석이 됨.
자바스크립트 컴파일러 입장에서는 Array 라는 문자열이 배열을 생성하는 식별자 라는 것을 알기 위해서 식별자 목록을 조회하게 됨

 

 

 

추가 테스트

위쪽에서는 var 형태로 배열을 생성하였고 리터럴 형태로 사용했을 때 배열의 생성속도가 더 빠른것을 확인하였음
추가로 let, const 형태로 배열을 선언하는 테스트를 해보았다.

console.time('using var []')
for(var i=0; i<2000000; i++){var arr = []};
console.timeEnd('using var []')
console.time('using var new')
for(var i=0; i<2000000; i++){var arr = new Array()} 
console.timeEnd('using var new')

console.time('using let []')
for(var i=0; i<2000000; i++){let arr1 = []};
console.timeEnd('using let []')
console.time('using let new')
for(var i=0; i<2000000; i++){let arr2 = new Array()} 
console.timeEnd('using let new')

console.time('using const []')
for(var i=0; i<2000000; i++){const arr1 = []};
console.timeEnd('using const []')
console.time('using const new')
for(var i=0; i<2000000; i++){const arr2 = new Array()} 
console.timeEnd('using const new')

결과

크롬, Node.js, 파이어폭스, 엣지브라우저에서 테스트를 진행한 결과

엔진별로 차이가 있지만 현재 가장 많이 사용되는 자바스크립트 엔진인 V8 엔진에서는
let, const로 배열을 생성 시 리터럴 방식과 객체방식간의 큰 성능 차이는 없는 것으로 보임

그러나 파이어폭스와 엣지 브라우저에서는 확연한 성능차이가 확인되었으며
사용자의 브라우저 환경을 특정할 수 없고 더 간편하고 안전한 배열 생성방식인 리터럴 방식으로 배열을 생성하는 것이 좋음
또한 배열은 가능하다면 const로 생성하는것이 좋다.

 

 

 

 

참고

http://45.55.116.124/javascript.html
http://www.ktword.co.kr/test/view/view.php?m_temp1=257
https://evan-moon.github.io/2019/06/25/hashtable-with-js/
https://poiemaweb.com/js-array-is-not-arrray
https://dh2note.tistory.com/115
https://ljlm0402.netlify.app/javascript/performance/
https://junwoo45.github.io/2019-11-04-memory_model/

'IT > 개발' 카테고리의 다른 글

프로미스 동작 분석하기(2)  (0) 2021.08.27
프로미스 동작 분석하기(1)  (0) 2021.08.21
SonicClassifier 웹페이지 추가 및 완성  (0) 2021.07.16
Airsonic 플레이리스트 정렬  (0) 2021.07.11
Simple Gallary Server  (0) 2021.01.10

+ Recent posts