목표
27. 배열
27-1. 배열이란?
const fruit = ['apple', 'banana', 'orange'];
- 배열은 여러 개의 값을 순차적으로 나열한 자료구조이다.
- 배열이 가지고 있는 값 하나하나를 요소(element) 라고 부른다.
- 자바스크립트의 모든 값(원시 값, 객체, 함수, 배열 등)은 배열의 요소가 될 수 있다.
const apple = fruit[0];
const banana = fruit[1];
- 배열의 요소는 자신의 위치를 나타내는 0 이상의 정수인 인덱스(index) 를 갖는다.
- 인덱스는 배열의 요소에 접근할 때 사용한다. 접근할 때에는
대괄호 [ ]
를 사용한다.
console.log(fruit.length);
- 배열은 길이를 나타내는 length 프로퍼티를 갖는다.
console.log(typeof arr);
- 자바스크립트에 배열이라는 타입이 존재하지 않는다. 배열은 객체 타입이다.
27-2. 자바스크립트의 배열은 객체이다.
- 위에서 typeof 연산자를 사용해 배열의 타입을 확인하면 object가 출력됐다.
- 그렇다면 자바스크립트에서 배열은 존재하지 않을까?
27-2-1. 밀집 배열(dense array)
- 자료구조(data structure)에서 흔히 말하는 배열은 동일한 크기의 메모리 공간이 빈틈없이 연속적으로 나열된 것을 말한다.
- 또한, 배열의 요소는 하나의 데이터 타입으로 통일되어 있으며 서로 인접해있다. 이러한 배열을 밀집 배열(dense array)이라 한다.
- 밀집 배열은 인덱스를 통해 효율적으로 요소에 접근할 수 있다는 장점이 있지만 정렬되지 않았다면 특정 요소를 발견할 때까지 차례대로 검색해야 하는 단점이 있다.
27-2-2. 희소 배열(sparse array)
- 자바스크립트의 배열은 밀집 배열과 다른데 배열의 요소가 동일한 크기의 메모리 공간을 갖지 않아도 되며, 연속적으로 이어져 있지 않을 수도 있다.
- 즉, 자바스크립트의 배열은 일반적인 배열의 동작을 흉내 낸 특수한 객체이다.
const arr = [
"string",
1,
true,
null,
undefined,
NaN,
[],
{ key1: {}, key2: {} },
];
- 자바스크립트 배열은 인덱스로 요소에 접근하는 일반적인 배열보다 느리지만 특정 요소를 검색하거나 요소를 삽입할 경우에는 빠르다.
- 대부분의 모던 자바스크립트 엔진은 일반 배열보다 느릴 수 밖에 없는 구조적인 단점을 보완하기 위해 더 배열처럼 동작하도록 최적화하여 구현했다.
27-3. length 프로퍼티와 희소 배열
- length 프로퍼티는 요소의 개수, 즉 배열의 길이를 나타내는 0 이상의 정수를 값으로 갖는다.
- 빈 배열일 경우 값은 0이며, 빈 배열이 아닐 경우 요소 중 가장 큰 인덱스에 1을 더한 것과 같다.
- length 프로퍼티의 값은 배열에 요소를 추가하거나 삭제하면 자동으로 갱신된다.
- 그리고 원래의 length 프로퍼티 값보다 작은 숫자 값을 할당하면 배열의 길이가 줄어든다.
const arr = [1, 2, 3, 4, 5];
arr.length = 3;
console.log(arr);
[1, 2, 3]
- 그렇다고 원래의 length 프로퍼티 값보다 큰 숫자 값을 할당해도 배열의 길이가 늘어나지 않는다.
const arr = [1];
arr.length = 3;
console.log(arr.length);
console.log(arr);
console.log(arr[1]);
3
(3) [1, 비어 있음 × 2]
undefined
- 위 출력 결과에서 비어 있음 x 2는 실제로 추가된 배열의 요소가 아니기 때문에 arr[1]과 arr[2]에는 값이 존재하지 않는다.
- 이처럼 자바스크립트의 배열은 배열의 요소가 연속적으로 위치하지 않고 일부가 비어 있는 희소 배열이다.
const sparse = [, 2, , 4];
console.log(sparse.length);
console.log(sparse);
4
(4) [비어 있음, 2, 비어 있음, 4]
- 일반적인 배열의 length는 배열의 개수 즉, 배열의 길이와 항상 일치한다. 하지만, 희소 배열은 length와 요소의 개수가 항상 일치하지는 않는다.
- 자바스크립트는 문법적으로 희소 배열을 허용하지만 희소 배열은 사용하지 않는 것이 좋다.
- 최적화가 잘 되어 있는 모던 자바스크립트 엔진은 요소의 타입이 일치하는 배열을 생성할 때 일반적인 의미의 배열처럼 연속된 메모리 공간을 확보하는 것으로 알려져 있다.
27-4. 배열 생성
27-4-1. 배열 리터럴
- 가장 일반적인 배열을 생성하는 방법으로 0개 이상의 요소를 쉼표로 구분해
대괄호 [ ]
로 묶는다.
const arr = [1, 2, 3];
27-4-2. Array 생성자 함수
- Object 생성자 함수를 통해 객체를 생성하듯이 Array 생성자 함수를 통해 배열을 생성할 수 있다.
const arr = new Array(10);
console.log(arr);
- Array 생성자 함수는 전달된 인수의 개수에 따라 다르게 동작하므로 주의가 필요하다.
- 인수가 하나라면 인수에 해당하는 숫자의 길이만큼 배열을 생성한다.
const arr = new Array(1, 2, 3);
console.log(arr);
- 인수의 개수가 2개 이상이면 인수를 요소로 갖는 배열을 생성한다.
27-4-3. Array.of
- ES6에 도입된 Array.of 메서드는 전달된 인수를 요소로 갖는 배열을 생성한다.
- Array 생성자 함수와는 다르게 전달된 인수가 1개이고 숫자이더라도 인수를 요소로 갖는 배열을 생성한다.
const arr1 = Array.of(1);
const arr2 = Array.of(1, 2, 3);
console.log(arr1);
console.log(arr2);
27-4-4. Array.from
- ES6에 도입된 Array.from 메서드는 유사 배열 객체 또는 이터러블 객체를 인수로 전달받아 배열로 변환하여 반환한다.
const arr1 = Array.from({length: 2, 0: 'a', 1: 'b'});
const arr2 = Array.from('hello');
console.log(arr1);
console.log(arr2);
- Array.from을 사용할 때 두 번째 인수로 콜백함수를 전달해 요소를 채울 수 있다.
Arrray.from({ length: 3 }, (_, i) => i);
27-5. 배열 요소의 참조
- 배열 요소를 참조할 때에는
대괄호 [ ]
표기법을 사용한다.
- 대괄호 안에는 정수로 평가되는 인덱스를 사용해야 한다.
const arr = [1, 2, 3];
console.log(arr[0]);
console.log(arr[1]);
console.log(arr[3]);
27-6. 배열 요소의 추가와 갱신
- 객체에 프로퍼티를 동적으로 추가할 수 있는 것처럼 배열에도 요소를 동적으로 추가할 수 있다.
- 존재하지 않는 인덱스를 사용해 값을 할당하면 새로운 요소가 추가된다. 이때, length 프로퍼티는 자동으로 갱신 된다.
const arr = [0];
arr[1] = 1;
console.log(arr.length);
- 이 때 명시적으로 값을 할당하지 않는 요소는 생성되지 않는다.
const arr = [1, 2, 3];
arr[5] = 6;
console.log(arr);
console.log(arr.length);
27-7. 배열 요소의 삭제
27-7-1. delete 연산자
- 배열의 요소를 삭제할 때에는 delete 연산자를 사용하는 방법이 있다.
const arr = [1, 2, 3];
delete arr[1];
console.log(arr);
console.log(arr.length);
- 위 예에선 배열 arr에서 프로퍼티 키가 1인 프로퍼티를 삭제한다.
- 이때, 배열은 희소 배열이 되고 length 프로퍼티값은 변하지 않는다.
- 희소 배열을 만들지 않기 위해 delete 연산자를 사용하지 않는 것이 좋다.
27-7-2. splice 메서드
- 희소 배열을 만들지 않으면서 배열의 특정 요소를 완전히 삭제하려면 Array.prototype.splice 메서드를 사용하면 된다.
const arr = [1, 2, 3];
arr.splice(1, 1);
console.log(arr);
console.log(arr.length);
Array.prototype.splice()
- splice() 메서드는 배열의 기존 요소를 삭제 또는 교체하거나 새 요소를 추가하여 배열의 내용을 변경한다.
array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
- 첫 번째 인수 start는 배열의 변경을 시작할 인덱스로 음수일 경우 배열의 끝에서 시작한다.
- deleteCount는 배열에서 제거할 요소의 수를 나타낸다.
- 반환 값은 제거한 요소를 담은 배열을 리턴한다.
const arr = [1, 2, 3];
const spliceArr = arr.splice(1, 2);
console.log(spliceArr);
console.log(arr);