자바스크립트(JavaScript) 배열에 대해 전체적으로 알고 싶어하는 사람들이 많길래 다시 정리해보기로 했다. 배열, 즉 Array
객체는 자바스크립트에서 가장 많이 사용하는 객체고 아주 쉽게 사용하지만 그러면서도 웬만한 개발자들이 잘 모르는 사실들도 많이 숨어 있는 커다란 창고 같은 객체다. 지난 번 글 자바스크립트 배열 길이는 좀더 자세하게 들여다본 내용이었는데 이번엔 개요라고 할 수 있겠다.
배열 선언
우선 배열 선언부터 보자.
var arr1 = new Array();
var arr2 = [];
var arr3 = new Array('a', 'b', 'c');
var arr4 = ['a', 'b', 'c'];
위에서 arr1
, arr2
는 동일한 선언으로서 빈 배열을 선언한다. arr3
, arr4는
세 개의 인자가 있는 배열을 선언한다. 그런데 다음과 같은 선언도 가능하다.
var arr5 = new Array(5);
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
메서드가 있어서 서로 반대의 기능을 한다.
var arr = ['<div class="', myClass, '" id="', myId, '">어떤 내용</div>'];
var str = arr.join(''); // 문자열을 더하기 기호로 이어붙인 것과 같다
arr = '1, 2, 3, 4, 5'.split(/, /);
str = arr.join(', '); // 원래 문자열이 된다
자바스크립트에는 문자열을 반복하는 기능이 따로 없지만 다음과 같이 함으로써 원하는 결과를 얻을 수 있다.
var str = new Array(10).join('사랑해!'); // "사랑해!"를 열 번 반복한다
concat
메서드, push
메서드
concat
은 배열에 요소를 추가하거나 배열에 배열을 더하는 메서드다.
var arr = ['소진', '유라', '민아', '혜리'].concat('지선');
// 위 arr 끝 요소로 '지선'이 붙는다.
var arr1 = ['효린', '보라'];
var arr2 = ['소유', '다솜'];
arr = arr1.concat(arr2); // arr은 ['효린', '보라', '소유', '다솜']이 된다
이와 비슷한 메서드로 push
가 있는데 push
는 배열을 이어붙일 때도 요소 한 개로서 붙인다.
var arr1 = ['효린', '보라', '소유', '다솜'];
var arr2 = ['소진', '유라', '민아', '혜리'];
arr = arr1.push(arr2);
// arr은 [['효린', '보라', '소유', '다솜'], ['소진', '유라', '민아', '혜리']]가 된다
concat
의 반대 기능을 하는 메서드는 없지만 push
의 반대 메서드로 pop
이 있다. pop
은 가장 마지막 요소를 떼어내서 반환한다.
sort
메서드
배열을 순서대로 정렬하는 메서드다. sort
의 인자로 함수를 줄 수 있는데 이 함수를 사용해 정렬 기준을 임의로 정해줄 수 있다. 이 함수에 인자 두 개를 받게 되는데 반환 값이 0이면 그 두 값이 같음을, 0보다 작으면 앞엣 값이 뒤엣 값보다 작음을, 크면 앞엣 값이 뒤엣 값보다 큼을 나타내게 되며 그에 따라 정렬해준다.
함수 인자가 없는 경우는 배열의 자연스러운 정렬 기준을 사용하게 된다. 예를 들어 숫자 자료형이라면 숫자 순서대로, 문자 자료형이라면 문자 순서대로 정렬한다. 역순 정렬이 필요하다면 위 규칙에 따라 정렬 함수를 만들되 반환 값을 반대로 하면 될 것이다.
// 기본 정렬. 결과는 ["너구리", "두시기", "석삼", "오징어", "육개장", "한놈"].
var arr = ['한놈', '두시기', '석삼', '너구리', '오징어', '육개장'].sort();
// 정렬 함수를 지정하는 정렬
arr = [obj1, obj2, obj3, obj4, obj5].sort(function (a, b) {
return a.name == b.name ? 0 : a.name < a.name ? -1 : 1;
});
위에서 6행은 어떤 객체 형태의 변수에서 name
필드를 가지고 비교를 하고 있다. 즉 obj1, obj2, … 등이 그 각각의 name
필드에 의해 순서가 바뀌게 된다.
splice
메서드
splice
메서드는 배열의 임의 위치에서 요소를 제거하고 추가할 수 있는 메서드다.
var arr = ['준형', '계상', '호영'].splice(1, 1, '데니', '태우');
// arr은 ['준형', '데니', '태우', '호영']이 된다
요소를 제거하고 추가하는 기능이 모두 있으므로 push
, pop
, shift
, unshift
메서드를 흉내낼 수 있다.
var arr = ['a', 'b', 'c'];
arr.splice(arr.length, 0, 'd'); // 이제 arr은 push를 한 것과 같다
arr.splice(arr.length, 1); // 이제 arr은 pop을 한 것과 같다
arr.splice(0, 0, 'e'); // 이제 arr은 unshift를 한 것과 같다
arr.splice(0, 1); // 이제 arr은 shift를 한 것과 같다
단, arr
의 결과는 동일하지만 splice
의 반환 값은 제거된 배열 요소들이므로 push
, unshift
와는 반환 값이 다르다.
DOM의 노드 리스트
예를 들어 elem.getElementsByTagName('div')
와 같은 식으로 DOM 개체를 배열처럼 가지고 올 수 있는데 이게 사실은 배열이 아니다. NodeList
라는 내부 자료형이라서 Array
객체의 메서드를 사용할 수 없다. length
같은 일부 속성은 Array
처럼 붙어 있으므로 사용할 수 있지만 Array
의 대부분의 메서드는 NodeList
에는 없다.
var myDiv = document.getElementById('myDiv');
var spans = myDiv.getElementsByTagName('span');
spans.push(document.createElement('span')); // 오류
이런 경우는 브라우저에 따라 간단한 방법이 있기도 하지만 모든 브라우저에서 다 되게 하려면(결국 IE 때문) 할 수 없이 요소 하나씩 배열에 복사해주는 수 밖에 없다.
var spans2 = [];
for (var i = 0; i < spans.length; ++i)
spans2.push(spans[i]);
spans2.push(document.createElement('span')); // 정상