이전 포스트에서도 알아봤듯이, 자바스크립트에서는 많은 것들이 객체로 간주된다. 그 중 하나가 바로 배열이다. 오늘은 웹개발을 하는 데 있어서 절대 빠질 수 없는 배열에 대해서 알아보고자 한다. 배열이란 무엇이고, 왜 자바스크립트에서는 배열을 객체라고 할까?
위키피디아에 따르면, 배열의 정의는 다음과 같다.
컴퓨터 과학에서 배열(Array) 은 번호(인덱스)와 번호에 대응하는 데이터들로 이루어진 자료 구조 를 나타낸다. 일반적으로 배열에는 같은 종류의 데이터들이 순차적으로 저장되어, 값의 번호가 곧 배열의 시작점으로부터 값이 저장되어 있는 상대적인 위치가 된다.
즉, 일반적으로 배열이란 동일한 크기의 메모리 공간이 빈틈없이 연속적으로 나열된 자료구조를 말한다. 보통 동질적인 타입의 값들이 저장되며, 순서에 의미가 있다. 이 순서를 통해 자료를 찾을 수도 있는데, 인덱스라는 값으로 자료를 O(1)의 시간복잡도로 탐색할 수 있다. 배열과 객체의 차이는 데이터들이 이 순서를 가지고 있는가이다.
const array = [1, 2, 3, 4, 5];
const object = { name: 'hale', position: 'developer' };
// 순서를 가지고 있는 Array는 인덱스를 통해 다음과 같이 자료를 찾을 수 있다.
console.log(array[0]);
// 순서를 가지고 있지 않은 객체는 key값을 알아야만 자료를 찾을 수 있다.
console.log(object.name);
일반적으로 배열은 내부 요소들의 타입이 일치하며, 연속적으로 메모리 공간이 인접해있다. 따라서 인덱스로 배열 요소에 매우 빠르게 접근할 수 있다. 그런데 자바스크립트의 배열은 이런 일반적인 의미의 배열과 조금 다르다. 자바스크립트의 getOwnPropertyDescriptors() 메서드를 통해 배열의 프로퍼티에 대한 값들을 출력해보자.
const array = [1, 2, 3, 4, 5];
console.log(Object.getOwnPropertyDescriptors(array));
// 다음과 같은 값들이 출력된다.
0: {value: 1, writable: true, enumerable: true, configurable: true}
1: {value: 2, writable: true, enumerable: true, configurable: true}
2: {value: 3, writable: true, enumerable: true, configurable: true}
3: {value: 4, writable: true, enumerable: true, configurable: true}
4: {value: 5, writable: true, enumerable: true, configurable: true}
length: {value: 5, writable: true, enumerable: false, configurable: false}
[[Prototype]]: Object
공간만 차지하는 빈 배열로 프로퍼티 값들을 출력해보면 다음과 같은 결과가 나온다.
const array = Array(5);
console.log(Object.getOwnPropertyDescriptors(array));
// console
length: {value: 5, writable: true, enumerable: false, configurable: false}
[[Prototype]]: Object
마치 유사 배열 구조와 같은, 배열은 아닌 것 같은 신기한 자료구조가 보인다. 이처럼 자바스크립트 배열은 인덱스를 프로퍼티의 키값으로 갖고 있으며, length를 프로퍼티로 갖는 특수한 객체다. 즉, 자바스크립트의 배열은 일반적인 배열의 동작을 흉내낸 객체에 불과한 셈이다. 따라서 다음과 같은 일관성 없는 값의 할당도 가능해진다.
let array = Array(10).fill(0);
array.name = 'array';
array['sayHello'] = () => console.log('Hello');
// array 결과
0: 0
1: 0
2: 0
3: 0
4: 0
5: 0
6: 0
7: 0
8: 0
9: 0
name: "array"
sayHello: () => console.log('Hello')
length: 10
[[Prototype]]: Array(0)
위의 코드처럼 어떠한 값이라도 자바스크립트 배열의 요소가 될 수 있다. 그러나 ‘특수한 객체’답게, length의 값은 배열의 길이를 그대로 유지한다. 반대로 length를 직접 조작하여 늘릴 수도 있다.
let array = Array(10).fill(0);
array.length = 5;
console.log(array);
// (5) [0, 0, 0, 0, 0]
array.length = 8;
console.log(array);
// (8) [0, 0, 0, 0, 0, empty × 3]
length를 줄이는 것은 실제 마지막 데이터들을 삭제하는 기능을 하지만, 한 번 삭제된 후 다시 length를 늘린다고 해서 데이터들이 돌아오지는 않는다. length를 늘려 배열 내부에 empty 값들이 생긴 배열을 희소 배열이라고 하는데, 이러한 특징은 알아만 두고 실제 코딩을 할 땐 가급적 사용하지 않는 게 좋겠다.
결론
자바스크립트의 배열은 길이도, 자료형도 고정되어있지 않다. 언제든지 동적으로 변형될 수 있으며 밀집성을 보장하지 않기에, 큰 프로젝트나 협업을 할 때에는 주의를 기울일 필요가 있다. 이를 보완하기 위해 나온 형식화 배열이라는 배열 구조도 존재한다는데, 추후 속도가 빠른 배열을 구현하고자 할 때 공부해보면 좋겠다.
Reference
'Javascript' 카테고리의 다른 글
[JavaScript] 객체의 불변성을 지키는 방법 (0) | 2023.02.12 |
---|---|
[JavaScript] 객체를 출력하는 방법 (0) | 2022.02.01 |
[JavaScript] i++ 와 ++i 의 차이 (0) | 2022.01.30 |
[JavaScript] switch문에서 break를 해줘야 하는 이유 (0) | 2022.01.12 |