개발 관련 도서

모던 자바스크립트 - 배열(1)

mrban 2024. 6. 18. 23:09

1. 배열이란?

배열은 여러 개의 값을 순차적으로 나열한 구조이다.

const a = ['반원재', '이규리'];

 

배열이 가지고 있는 값을 요소(element)라고 한다. 배열의 요소는 배열에서 자신의 위치를 나타내는 0 이상의 정수인 인덱스를 가진다. 인덱스는 0부터 시작된다.

 

a[0]; //'반원재'
a[1]; //'이규리'

 

배열은 배열의 길이를 나타내는 length 프로퍼티를 가진다.

 

a.length; // 2

 

배열은 객체 타입이다. 하지만 객체와의 결정적인 차이가 존재하는데 바로 배열은 값의 순서가 존재하고. length 프로퍼티를 사용할 수 있다는 점이다. 즉, 배열의 장점은 처음부터 순차적으로 요소에 접근이 가능하다는 장점이 있다.

 

2. 자바스크립트 배열은 일반적인 배열의 개념이 아니다!

 

우리가 알고 있는 일반적인 배열이란 밀집 배열로 동일한 크기의 메모리 공간이 빈틈없이 연속적으로 나열된 자료구조를 뜻한다.

 

 

따라서 배열은 인덱스를 통해 효율적으로 요소에 접근할 수 있다는 장점이 있다. 또한 배열 요소를 삽입하거나 삭제하는 경우 배열의 요소를 연속적으로 유지하기 위해 요소를 이동시켜야 하는 단점도 있다.

 

 

근데 자바스크립트 배열은 이러한 일반적인 배열과는 다르게 희소 배열로 각각의 메모리 공간이 동일한 크기를 갖지 않아도 되며, 연속적으로 이어져 있지 않을 수도 있다. 이는 자바스크립트의 배열은 일반적인 배열의 동작을 흉내 낸 특수한 객체라고 할 수 있다.

 

console.log(Object.getOwnPropertyDescriptors([1, 2, 3]));
/*
{
  '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 },
  length: { value: 3, writable: true, enumerable: false, configurable: false }
}
*/

 

어떤 타입의 값도 배열의 요소가 될 수 있다. 

결론적으로 자바스크립트의 배열은 객체이기 때문에 일반적인 배열보다 인덱스로 배열 요소에 접근하는 것은 느리지만, 요소를 삽입 또는 삭제하는 경우에는 일반적인 배열보다 빠르다. 모던 자바스크립트 엔진은 배열을 일반 객체와 구별하여 좀 더 배열처럼 동작하도록 최적화하여 구현하여 일반 객체보다 배열이 그래도 약 2배정도 빠르다.

 

3. length 프로퍼티

length 프로퍼티 값은 배열의 길이를 바탕으로 결정되지만 임의의 숫자 값을 명시적으로 할당할 수도 있다. 작은 숫자를 할당하면 배열의 길이가 준다.

 

const arr = [1, 2, 3];

arr.length = 1;

console.log(arr); // [1]

 

다만 반대로 length 프로퍼티 값보다 큰 숫자를 할당해도 배열의 길이가 늘어나지 않는다.

 

이처럼 배열의 요소가 연속적으로 위치하지 않고 일부가 비어있는 배열을 희소배열이라고 한다.

// 희소배열
const spare = [, 2, , 4];

console.log(spare.length); //4
console.log(spare); // [empty, 2, empty, 4];

 

일반적인 배열은 length와 배열의 길이가 언제나 일치하지만, 희소배열은 length와 배열 요소의 개수가 일치하지 않을 수 있다. 배열을 생성할 경우에는 희소 배열을 생성하지 않도록 주의하자. 배열의 기본 개념과 맞지 않고 성능에도 좋지 않다. 개념 정도만 이해하자.

 

3. 배열 생성

  • 배열 리터럴

가장 일반적인 방식이다.

 

const arr = [1, 2, 3];

arr.length = 1;

console.log(arr); // [1]

 

  • Array 생성자 함수
const arr = new Array(10);

// 희소배열이 만들어진다.
console.log(arr); // [empty * 10]

// 아무 인수도 안넘겨주면 빈배열 생성
const arr1 = new Array();
console.log(arr1); // []

// 전달된 인수가 2개 이상이면 인수를 요소로 갖는 배열을 생성한다.
new Array(1, 2, 3); // [1, 2, 3];
  • Array.of

ES6에서 도입된 메서드인데 전달된 인수를 요소로 갖는 배열을 생성한다. Array 생성자와 다르게 전달된 인수가 1개이더라도 인수를 요소로 갖는 배열을 만든다.

 

Array.of(1); // [1]
  • Array.from

ES6에 도입된 메서드로 유사배열객체 또는 이터러블 객체를 인수로 전달받아 배열로 변환하여 반환한다. 유사배열객체란 배열처럼 인덱스로 프로퍼티 값에 접근할 수 있고 length 프로퍼티를 갖는 객체를 말한다. 이터러블은 뒤에서 자세히...

 

Array.from({length:2, 0: 'a', 1: 'b'}); // ['a', 'b']

Array.from('Hi'); // ['H', 'i']

Array.from({length: 3}, (_, i) => i); // [0, 1, 2]

 

4. 배열 요소의 참조

존재하지 않는 요소에 접근하면 undefined 반환한다.

 

const arr = [1, 2];

console.log(arr[2]); // undefined

 

5. 배열 요소의 추가와 갱신

객체에 프로퍼티를 동적으로 추가할 수 있는 것처럼 배열에도 요소를 동적으로 추가할 수 있다. 존재하지 않는 인덱스를 사용해 값을 할당하면 새로운 요소가 추가된다. 이때 length 프로퍼티 값은 자동으로 갱신된다.

 

const arr = [0];

arr[1] = 1;

console.log(arr); // [0, 1];
console.log(arr.length); // 2

// 값을 갱신할 수도 있다.
arr[1] = 3;

console.log(arr); //[0, 3];

 

5. 배열 요소의 삭제

배열은 객체이기 때문에 delete연산자를 사용할 수 있다.

const arr = [1, 2, ,3];

delete arr[1];
console.log(arr); // [1, empty, 3]

console.log(arr.length); // 3

 

희소배열이 생성될 수 있기 때문에 delete연산자는 사용하지 않는 것이 좋다. 희소배열을 만들지 않으면서 배열의 특정 요소를 완전히 삭제하려면 splice 메서드를 사용하자

 

const arr = [1, 2, 3];

arr.splice(1, 1);

console.log(arr); //[1, 3]

// length 길이도 준다!
console.log(arr.length); // 2