자바스크립트 배열을 다시 알아보자

자바스크립트(JavaScript) 배열에 대해 전체적으로 알고 싶어하는 사람들이 많길래 다시 정리해보기로 했다. 배열, 즉 Array 객체는 자바스크립트에서 가장 많이 사용하는 객체고 아주 쉽게 사용하지만 그러면서도 웬만한 개발자들이 잘 모르는 사실들도 많이 숨어 있는 커다란 창고 같은 객체다. 지난 번 글 자바스크립트 배열 길이는 좀더 자세하게 들여다본 내용이었는데 이번엔 개요라고 할 수 있겠다.

배열 선언

우선 배열 선언부터 보자.

  1. var arr1 = new Array();
  2. var arr2 = [];
  3. var arr3 = new Array('a', 'b', 'c');
  4. var arr4 = ['a', 'b', 'c'];

위에서 arr1, arr2는 동일한 선언으로서 빈 배열을 선언한다. arr3, arr4는 세 개의 인자가 있는 배열을 선언한다. 그런데 다음과 같은 선언도 가능하다.

  1. var arr5 = new Array(5);
  2. var arr6 = [5];

arr5는 인자가 하나 있는 배열을 선언하는 게 아니라 길이가 5, 즉 요소를 다섯 개 넣는 배열을 선언한다. 하지만 arr6은 인자가 하나 있는 배열이다. 차이는 Array 생성자가 두 가지 인자를 받는다는 데 있다. 숫자 자료형 하나만을 인자로 주면 배열 길이가 되고 문자열이나 다른 객체를 인자로 주면 배열 요소가 된다. (그런데 숫자더라도 음수나 소수, 32비트를 넘는 자연수를 주면 오류 발생) 하지만 [] 선언식은 항상 배열 요소를 인자로 받는다. 이러한 사실은 브라우저 콘솔에서 다음과 같이 확인해볼 수 있다.

>>> new Array(5).length
5
>>> [5].length
1
>>> new Array(-10).length
RangeError: invalid array length
>>> new Array(987654321).length
987654321
>>> new Array(9876543210).length
RangeError: invalid array length

자바스크립트 배열은 요소를 추가하는 대로 알아서 그 크기가 늘어나므로 사실 위처럼 처음부터 요소 개수를 선언해 놓는 경우가 많지는 않지만 두 가지 다른 선언 방식이 있다는 사실은 반드시 알고 있어야 한다.

마지막으로 하나, 배열 길이는 아무리 크게 잡아도 실제로 메모리를 차지하는 것은 배열 요소의 값을 실제로 넣은 경우에만 발생한다.

join 메서드

자바스크립트 문자열 자료형에는 split 메서드가 있고 배열 자료형에는 join 메서드가 있어서 서로 반대의 기능을 한다.

  1. var arr = ['<div class="', myClass, '" id="', myId, '">어떤 내용</div>'];
  2. var str = arr.join(''); // 문자열을 더하기 기호로 이어붙인 것과 같다
  3. arr = '1, 2, 3, 4, 5'.split(/, /);
  4. str = arr.join(', '); // 원래 문자열이 된다

자바스크립트에는 문자열을 반복하는 기능이 따로 없지만 다음과 같이 함으로써 원하는 결과를 얻을 수 있다.

  1. var str = new Array(10).join('사랑해!'); // "사랑해!"를 열 번 반복한다

concat 메서드, push 메서드

concat은 배열에 요소를 추가하거나 배열에 배열을 더하는 메서드다.

  1. var arr = ['소진', '유라', '민아', '혜리'].concat('지선');
  2. // 위 arr 끝 요소로 '지선'이 붙는다.
  3. var arr1 = ['효린', '보라'];
  4. var arr2 = ['소유', '다솜'];
  5. arr = arr1.concat(arr2); // arr은 ['효린', '보라', '소유', '다솜']이 된다

이와 비슷한 메서드로 push가 있는데 push는 배열을 이어붙일 때도 요소 한 개로서 붙인다.

  1. var arr1 = ['효린', '보라', '소유', '다솜'];
  2. var arr2 = ['소진', '유라', '민아', '혜리'];
  3. arr = arr1.push(arr2);
  4. // arr은 [['효린', '보라', '소유', '다솜'], ['소진', '유라', '민아', '혜리']]가 된다

concat의 반대 기능을 하는 메서드는 없지만 push의 반대 메서드로 pop이 있다. pop은 가장 마지막 요소를 떼어내서 반환한다.

sort 메서드

배열을 순서대로 정렬하는 메서드다. sort의 인자로 함수를 줄 수 있는데 이 함수를 사용해 정렬 기준을 임의로 정해줄 수 있다. 이 함수에 인자 두 개를 받게 되는데 반환 값이 0이면 그 두 값이 같음을, 0보다 작으면 앞엣 값이 뒤엣 값보다 작음을, 크면 앞엣 값이 뒤엣 값보다 큼을 나타내게 되며 그에 따라 정렬해준다.

함수 인자가 없는 경우는 배열의 자연스러운 정렬 기준을 사용하게 된다. 예를 들어 숫자 자료형이라면 숫자 순서대로, 문자 자료형이라면 문자 순서대로 정렬한다. 역순 정렬이 필요하다면 위 규칙에 따라 정렬 함수를 만들되 반환 값을 반대로 하면 될 것이다.

  1. // 기본 정렬. 결과는 ["너구리", "두시기", "석삼", "오징어", "육개장", "한놈"].
  2. var arr = ['한놈', '두시기', '석삼', '너구리', '오징어', '육개장'].sort();
  3.  
  4. // 정렬 함수를 지정하는 정렬
  5. arr = [obj1, obj2, obj3, obj4, obj5].sort(function (a, b) {
  6.     return a.name == b.name ? 0 : a.name < a.name ? -1 : 1;
  7. });

위에서 6행은 어떤 객체 형태의 변수에서 name 필드를 가지고 비교를 하고 있다. 즉 obj1, obj2, … 등이 그 각각의 name 필드에 의해 순서가 바뀌게 된다.

splice 메서드

splice 메서드는 배열의 임의 위치에서 요소를 제거하고 추가할 수 있는 메서드다.

  1. var arr = ['준형', '계상', '호영'].splice(1, 1, '데니', '태우');
  2. // arr은 ['준형', '데니', '태우', '호영']이 된다

요소를 제거하고 추가하는 기능이 모두 있으므로 push, pop, shift, unshift 메서드를 흉내낼 수 있다.

  1. var arr = ['a', 'b', 'c'];
  2. arr.splice(arr.length, 0, 'd'); // 이제 arr은 push를 한 것과 같다
  3. arr.splice(arr.length, 1); // 이제 arr은 pop을 한 것과 같다
  4. arr.splice(0, 0, 'e'); // 이제 arr은 unshift를 한 것과 같다
  5. arr.splice(0, 1); // 이제 arr은 shift를 한 것과 같다

단, arr의 결과는 동일하지만 splice의 반환 값은 제거된 배열 요소들이므로 push, unshift와는 반환 값이 다르다.

DOM의 노드 리스트

예를 들어 elem.getElementsByTagName('div')와 같은 식으로 DOM 개체를 배열처럼 가지고 올 수 있는데 이게 사실은 배열이 아니다. NodeList라는 내부 자료형이라서 Array 객체의 메서드를 사용할 수 없다. length 같은 일부 속성은 Array처럼 붙어 있으므로 사용할 수 있지만 Array의 대부분의 메서드는 NodeList에는 없다.

  1. var myDiv = document.getElementById('myDiv');
  2. var spans = myDiv.getElementsByTagName('span');
  3. spans.push(document.createElement('span')); // 오류

이런 경우는 브라우저에 따라 간단한 방법이 있기도 하지만 모든 브라우저에서 다 되게 하려면(결국 IE 때문) 할 수 없이 요소 하나씩 배열에 복사해주는 수 밖에 없다.

  1. var spans2 = [];
  2. for (var i = 0; i < spans.length; ++i)
  3.     spans2.push(spans[i]);
  4. spans2.push(document.createElement('span')); // 정상

자바스크립트 배열을 다시 알아보자”에 대한 의견

  1. 글 잘 읽었습니다.^^
    다만 getElementsByTagName은 아마 NodeList가 아니라 HTMLCollection을 반환할 것입니다. querySelector의 경우가 NodeList입니다.(둘의 특성이 꽤 달라서 댓글남깁니다.)

의견 있으시면 냉큼 작성해주세요~