🚀 94sssh
Published on

2024.08.01

Edited 2024.08.06

[딥다이브] - 27. 배열(1)

27.1. 배열이란?

배열은 여러 개의 요소를 순차적으로 나열한 자료구조다.

자바스크립트에 배열이라는 타입은 존재하지 않는다. 배열은 객체 타입이다.

배열은 객체지만 일반 객체와는 다르다.

구분객체배열
구조프로퍼티 키와 프로퍼티 값인덱스와 요소
값의 참조프로퍼티 키인덱스
값의 순서XO
length 프로퍼티XO

27.2. 자바스크립트 배열은 배열이 아니다

  • 자료구조의 배열

    • 동일한 크기의 메모리 공간이 빈틈없이 연속적으로 나열된 자료구조
    • 하나의 데이터 타입으로 통일되어 있으며 서로 연속적으로 인접(밀집 배열)
    • 인덱스를 통해 효율적으로 요소에 접근할 수 있음
    • 배열에 요소를 삽입하거나 삭제하는 경우 요소를 이동시켜야 하는 단점
  • 자바스크립트 배열

    • 각각의 메모리 공간이 동일한 크기를 갖지 않아도 됨
    • 요소가 연속적으로 이어져 있지 않아도 됨(희소 배열)
    • 일반적인 배열의 동작을 흉내 낸 특수한 객체
    • 해시 테이블로 구현된 객체이므로 인덱스로 요소에 접근하는 경우 일반적인 배열보다 성능적으로 느릴 수 밖에 없는 구조적인 단점
    • 요소를 삽입 또는 삭제하는 경우에는 일반적인 배열보다 빠른 성능을 기대할 수 있음

27.3. length 프로퍼티와 희소 배열

length 프로퍼티는 배열의 길이를 나타내는 0 이상의 정수(0 ~ 2³²- 1(4, 294,967,296 - 1))를 값으로 갖는다.

length 프로퍼티의 값은 배열에 요소를 추가하거나 삭제하면 자동 갱신된다.
length 프로퍼티는 임의의 숫자 값을 명시적으로 할당할 수 있는데, 현재 length 프로퍼티 값보다 작은 숫자 값을 할당하면 배열의 길이가 줄어들고 큰 숫자 값을 할당하면 length 프로퍼티 값은 변경되지만 실제 배열의 길이가 늘어나진 않는다.

희소 배열은 배열의 요소가 연속적으로 위치하지 않고 일부가 비어 있는 배열로, 자바스크립트는 희소 배열을 허용하는데 희소 배열은 length와 배열 요소의 개수가 일치하지 않는다. 희소 배열은 사용하지 않는 것이 좋으며 배열의 기본 개념과 맞지 않고 성능에도 좋지 않다. 배열에는 같은 타입의 요소를 연속적으로 위치시키는 것이 최선이다.

27.4. 배열 생성

27.4.1. 배열 리터럴

배열 리터럴은 0개 이상의 요소를 쉼표로 구분하여 대괄호([])로 묶는다.

const arr = [1, 2, 3]
console.log(arr.length) // 3

27.4.2. Array 생성자 함수

Array 생성자 함수는 전달된 인수의 개수에 따라 다르게 동작한다.

  • 전달된 인수가 1개이고 숫자인 경우 length 프로퍼티 값이 인수인 배열을 생성
const arr = new Array(10) // [empty * 10]
  • 전달된 인수가 없는 경우 빈 배열 생성
new Array() // []
  • 전달된 인수가 2개 이상이거나 숫자가 아닌 경우 인수를 요소로 갖는 배열 생성
new Array(1, 2, 3) // [1, 2, 3]
new Array({}) // [{}]

27.4.3. Array.of

ES6에서 도입된 Array.of는 전달된 인수를 요소로 갖는 배열을 생성한다. Array 생성자 함수와 다르게 전달된 인수가 1개이고 숫자이더라도 인수를 요소로 갖는 배열을 생성한다.

Array.of(1) // [1]
Array.of(1, 2, 3) // [1, 2, 3]
Array.of('string') // ['string']

27.4.4. Array.from

ES6에서 도입된 Array.from은 유사 배열 객체 또는 이터러블 객체(Array, String, Map, Set, DOM 컬렉션(NodeList, HTMLCollection), arguments)를 인수로 전달받아 배열로 변환하여 리턴한다.

// 유사 배열 객체를 변환하여 배열을 생성
Array.from({ length: 2, 0: 'a', 1: 'b' }) // ['a', 'b']

// 이터러블을 변환하여 배열을 생성, 문자열은 이터러블
Array.from('Hello') // ['H', 'e', 'l', 'l', 'o']

27.5. 배열 요소의 참조

배열의 요소를 참조할 때는 대괄호 표기법([])을 사용한다. 대괄호 안에는 인덱스나 정수로 평가되는 표현식을 사용한다.
존재하지 않는 요소에 접근하면 undefined를 리턴한다.

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

배열에 요소를 동적으로 추가할 수 있다. 존재하지 않는 인덱스를 사용해 값을 할당하면 새로운 요소가 추가되며, length 프로퍼티 값이 갱신된다. 명시적으로 값을 할당하지 않은 요소는 생성되지 않으며, 이미 요소가 존재하는 요소에 값을 재할당하면 요소값이 갱신된다.

정수 이외의 값을 인덱스처럼 사용하면 요소가 아닌 프로퍼티가 생성되며, length 프로퍼티 값에 영향을 주지 않는다.

27.7. 배열 요소의 삭제

배열은 사실 객체이므로 delete 연산자를 사용할 수 있다. 이때 배열은 희소 배열이 되며 length 프로퍼티 값은 변하지 않는다. 따라서 delete 연산자는 사용하지 않는 것이 좋다.

희소 배열을 만들지 않고 특정 요소를 삭제하려면 Array.prototype.splice 메서드를 사용한다.

27.8. 배열 메서드

배열 메서드는 결과물을 리턴하는 패턴이 두 가지로 주의가 필요하다.

  • 원본 배열을 직접 변경하는 메서드
  • 원본 배열을 직접 변경하지 않고 새로운 배열을 생성하여 리턴하는 메서드

27.8.2. Array.prototype.indexOf

원본 배열에서 인수로 전달된 요소를 검색하고 인덱스를 리턴한다. 두 번째 인수로 검색을 시작할 인덱스를 전달할 수 있으며, 생략시 처음부터 검색한다.

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

arr.indexOf(2, 2) // 2

27.8.3. Array.prototype.push

성능 면에서 length 프로퍼티를 사용해 배열의 마지막에 요소를 추가하는 것이 push 메서드보다 빠르다.

const arr = [1, 2]

arr[arr.length] = 3
console.log(arr) // [1, 2, 3]

27.8.13. Array.prototype.includes

ES7에서 도입된 메서드로 배열 내에 특정 요소가 포함되어 있는지 확인해 true 또는 false를 리턴한다.
첫 번째 인수로 검색할 대상을 지정하고, 두 번째 인수로 검색을 시작할 인덱스를 전달할 수 있다. 생략할 시 기본값 0이 설정된다.

const arr = [1, 2, 3]

arr.includes(2) // true
arr.includes(100) // false
arr.includes(1, 1) // false