자바스크립트 배열 길이는 동적으로 변한다. 그렇다면 배열 변수 선언이나 요소 정의, 삭제 등의 조작에 따라 그 값이 어떻게 달라질까? 다음은 구글 크롬 브라우저의 콘솔 창에서 배열을 선언하고 요소를 추가하는 과정을 보인 것이다. 다른 브라우저에서도 유사한 결과를 볼 수 있다.
> x = []; x.length;
0
> x[10] = 123; x.length;
11
> typeof x[0]
"undefined"
> typeof x[10]
"number"
> x
[undefined × 10, 123]
위에서 보면 x라는 배열 변수를 선언하고 2행에서 10번 요소에 값을 설정하자 그 길이가 0에서 11로 바뀌는 것을 볼 수 있다. (그런데 x[0]
~ x[9]
까지는 "undefined"
이기 때문에, 즉 존재하지 않기 때문에 메모리를 차지하지 않는다. 자바스크립트 배열 길이는 열 한개지만 메모리는 한 개 분량만 차지하는 것이다.)
배열 요소를 삭제해보자.
> delete x[10]
true
> x
[undefined × 11]
> x.splice(10, 1)
[undefined × 1]
> x
[undefined × 10]
delete
로 배열 요소를 삭제할 때는 값만 사라지고 배열 길이가 줄어들지 않는 것을 볼 수 있다. 그런데 5행에서 splice
함수로 배열 요소를 잘라내면 배열 길이가 줄어든다. 뭔가 예상과는 다른가?
결론부터 말하자면 JavaScript 배열은 말만 배열일 뿐 실제로는 객체와 동일하게 동작하고 배열 길이를 나타내는 length
속성만 하나 더 관리되는 것이기 때문인 것이다. delete
로 10번 요소는 완전히 사라졌지만 length
값을 별도로 관리하기 때문에 요소 개수가 여전히 11인 것처럼 나온 것이고 splice
같은 배열 함수를 사용하자 length
값이 변하는 것이다.
배열을 조작할 때 배열 색인은 실제로는 객체의 속성과 똑같은 역할이다. for
문은 객체의 속성 키를 모두 뽑아낼 수 있다. 배열과 객체를 비슷하게 선언한 후 속성 값을 확인해보자.
> x = []; x[10] = 123;
123
> x[10]
123
> x['10']
123
> s = ''; for (var key in x) s += key + ' = ' + x[key] + '\n'; s;
"10 = 123
"
> x = {10: 123};
Object {10: 123}
> s = ''; for (var key in x) s += key + ' = ' + x[key] + '\n'; s;
"10 = 123
"
> x[10]
123
> x['10']
123
이상에서 배열과 객체는 선언하는 방법은 다르지만 실제 데이터는 똑같이 들어있고 똑같이 액세스할 수 있음을 알 수 있다. 배열에서 x[10] = 123
이라고 값을 넣는 것은 실제로는 객체에 '10’이라는 속성을 주는 것과 같은 것이다. 즉, JavaScript 배열은 다른 언어에서 일반적으로 생각하듯 연속된 메모리를 할당한 후 그 메모리의 첫번째 칸에는 뭘 넣고 두번째 칸에는 뭘 넣고… 이런 식이 아니라 배열 요소마다 따로따로 메모리를 할당하여 값을 넣는 방식이라 할 수 있다.
배열과 객체는 결국 같은 방식으로 조작할 수 있으며 동작 방식 또한 전혀 차이가 없다고 생각하면 된다.
> x = []; x[10] = 123; x['name'] = '변수';
"변수"
> s = ''; for (var key in x) s += key + ' = ' + x[key] + '\n'; s;
"10 = 123
name = 변수
"
> x = {10: 123, name:'변수'};
Object {10: 123, name: "변수"}
> s = ''; for (var key in x) s += key + ' = ' + x[key] + '\n'; s;
"10 = 123
name = 변수
"