본문 바로가기
Books/모던 JS Deep Dive ✔️

[모던 JS Deep Dive] 27장 - 배열

by Aaron-Kim 2022. 1. 14.

27.1 배열이란?

  - 배열의 길이를 나타내는 length 프로퍼티

  - 배열을 생성하는 4가지 방법

    - 배열 리터럴

    - Array 생성자 함수

    - Array.of

    - Array.from

  - Array.prototype은 배열을 위한 빌트인 메서드 제공

  - 객체 vs. 배열

    - 객체; 값의 순서 X, length 프로퍼티 X

    - 배열; 값의 순서 O, length 프로퍼티 O

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

  - JS 배열은 배열의 요소가 연속적으로 이어져 있지 않은 Sparse array (희소 배열)

    - JS 배열은 일반적인 배열의 동작을 흉내 낸 특수한 객체

    - JS 배열은 인덱스를 나타내는 문자열을 프로퍼티 키로 가지며, length 프로퍼티 갖는 특수한 객체
      (JS 배열의 요소는 사실 프로퍼티의 값)

  - JS 배열은 해시 테이블로 구현된 객체임

27.3 length 프로퍼티와 희소 배열

  - length 프로퍼티 값은 0 ~ 2^32 - 1 미만의 양의 정수

    - 배열에서 사용할 수 있는 가장 작은 인덱스는 0, 가장 큰 인덱스는 2^32 - 2

  - 현재 length 프로퍼티 값보다 큰 숫자 값 할당하게 되면, length 프로퍼티 값은 변경되지만

    실제로 배열의 길이가 늘어나지는 않음 (empty로 표현됨)

    - 값 없이 비어 있는 요소를 위해 메모리 공간 확보 X, 빈 요소 생성 X

  - 희소 배열의 length 프로퍼티 값은 요소의 개수와 일치하지 않음

  - 배열에는 같은 타입의 요소를 연속적으로 위치시키는 것이 최선임!

27.4 배열 생성

  - 배열 리터럴

    - 0개 이상의 요소를 쉼표로 구분하여 대괄호로 묶음

  - Array 생성자 함수

    - 전달된 인수의 개수에 따라 다르게 동작함

    - 전달된 인수 개수가 0개이면 빈 배열 생성

    - 전달된 인수 개수 1개이고 숫자인 경우, length 프로퍼티 값이 인수인 배열 생성

      - 희소 배열, length 프로퍼티 값은 0이 아니지만 실제로 배열의 요소가 존재하지는 않음

    - 전달된 인수 개수가 2개 이상 or 숫자가 아닌 경우 인수를 요소로 갖는 배열 생성

    - new 연산자와 함께 호출하지 않고 일반 함수로서 호출해도 배열을 생성하는 생성자 함수로서 동작함

      - Array 생성자 함수 내부에서 new.target을 확인하기 때문

  - Array.of (ES6)

    - 전달된 인수를 요소로 갖는 배열 생성

  - Array.from (ES6)

    - 유사 배열 객체 or 이터러블 객체를 인수로 전달받아 배열로 변환하여 반환

    - 두 번째 인수로 전달한 콜백 함수를 통해 값을 만들면서 요소 채우기 가능

27.5 배열 요소의 참조

  - 대괄호 표기법 사용

  - 존재하지 않은 요소를 참조하면 undefined 반환 (희소 배열의 empty 부분 참조해도 동일)

27.6 배열 요소의 추가와 갱신

  - 존재하지 않는 인덱스를 사용해 값을 할당하면 새로운 요소가 추가됨 (length 프로퍼티 값은 자동 갱신)

  - 이미 요소가 존재하는 요소에 값을 재할당하면 요소 값이 갱신됨

  - 인덱스로 정수 (or 정수 형태의 문자열, 정수로 평가되는 표현식) 이외의 값을 사용하면 프로퍼티가 생성됨,

    추가된 프로퍼티는 length 프로퍼티 값에 영향 주지 않음

27.7 배열 요소의 삭제

  - delete 연산자 사용 가능 (length 프로퍼티에는 영향 주지 않음, 희소 배열이 됨)

  - 희소 배열을 만들지 않으면서 배열의 특정 요소 완전히 삭제 위해 Array.prototype.splice() 메서드 사용

    - length 프로퍼티도 자동 갱신됨

    - Array.prototype.splice(삭제 시작할 인덱스, 삭제할 요소 개수)

27.8 배열 메서드

  - Array.isArray

    - Array 생성자 함수의 정적 메서드

    - 전달된 인수가 배열이면 true, 배열이 아니면 false 반환

  - Array.prototype.indexOf

    - 원본 배열에서 인수로 전달된 요소를 검색하여 인덱스 반환

    - 두 번째 인수는 검색을 시작할 인덱스, 생략 시 처음부터 검색함

    - 중복되는 여러 요소 있으면 첫 번째로 검색된 요소의 인덱스 반환

    - 인수로 전달한 요소가 존재하지 않으면 -1 반환

    - 배열에 특정 요소가 존재하는지 확인할 때 유용

      - ES7 Array.prototype.includes 메서드 사용 시 가독성 더 좋음

  - Array.prototype.push

    - 인수로 전달받은 모든 값을 원본 배열의 마지막 요소로 추가, 변경된 length 프로퍼티 값 반환

    - 성능 면에서 좋지 않음

      - legnth 프로퍼티 사용하여 배열의 마지막에 요소 직접 추가도 가능 (push 메서드보다 빠름)

    - 원본 배열 직접 변경 (mutator method) <- side-effect 주의!

      - ES6 스프레드 문법 사용하면 side-effect 없음!

  - Array.prototype.pop

    - 원본 배열에서 마지막 요소 제거하고 제거한 요소 반환

    - 원본 배열 직접 변경

    - pop 메서드와 push 메서드 사용하여 스택 쉽게 구현 가능

  - Array.prototype.unshift

    - 인수로 전달받은 모든 값을 원본 배열의 선두에 요소로 추가, 변경된 length 프로퍼티 값 반환

    - 원본 배열 직접 변경

      - ES6 스프레드 문법 사용 권장

  - Array.prototype.shift

    - 원본 배열에서 첫 번째 요소 제거하고 제거한 요소 반환

    - 원본 배열 직접 변경

    - shift 메서드와 push 메서드 사용하면 쉽게 구현 가능

  - Array.prototype.concat

    - 인수로 전달된 값들(배열 또는 원시값)을 원본 배열의 마지막 요소로 추가한 새로운 배열 반환

      - 인수로 전달받은 배열을 해체하여 새로운 배열의 요소로 추가

    - 새로운 배열 생성하여 반환 (accessor method) <- 권장!

      - push와 unshift 메서드는 concat 메서드로 대체 가능 (반환값을 변수에 할당해야 함)

      - concat 메서드는 ES6 스프레드 문법으로 대체 가능 (권장)

  - Array.prototype.splice

    - 원본 배열의 중간에 요소 추가/제거할 때 사용

    - 원본 배열 직접 변경

    - 3개의 매개변수 (startIndex, deleteCount, InsertItems)

      - 제거한 요소가 배열로 반환됨

      - 두 번째 인수 생략하면 첫 번째 인수로 전달된 시작 인덱스부터 모든 요소 제거

      - 배열에서 특정 요소 제거하려면 indexOf 메서드 같이 활용

      - filter 메서드 사용하여 중복된 특정 요소 모두 제거 가능

  - Array.prototype.slice

    - 인수로 전달된 범위의 요소들을 복사하여 배열로 반환

    - 원본 배열 보존됨

    - 2개의 매개변수 (startIndex, endIndex)

      - endIndex는 exclusive

      - endIndex 생략 가능 (기본값은 length 프로퍼티 값)

      - 인수 모두 생략하면 원본 배열의 복사본 생성하여 반환

    - slice 메서드, 스프레드 문법, Object.assign 메서드 모두 얕은 복사 수행

      (깊은 복사를 위해 Lodash 라이브러리의 cloneDeep 메서드 사용 권장)

    - slice 메서드를 이용하면 유사 배열 객체를 배열로 변환 가능 (ES5)

      - Array.from 메서드 사용하면 더 간단하게 유사 배열 객체 또는 이터러블 객체를 배열로 변환 가능

      - 사실 ES6 스프레드 문법 사용하면 매우 간단함

  - Array.prototype.join

    - 원본 배열의 모든 요소를 문자열로 변환한 후, 인수로 전달받은 문자열(구분자)로 연결한 문자열 반환

  - Array.prototype.reverse

    - 원본 배열의 순서를 반대로 뒤집음

    - 원본 배열이 변경됨

  - Array.prototype.fill

    - ES6, 인수로 전달받은 값을 배열의 처음부터 끝까지 요소로 채움

    - 두 번째 인수로 요소 채우기 시작할 인덱스 설정 가능

    - 배열 생성하면서 특정 값 요소로만 채우기 가능

      - Array.from 메서드와 같이 활용하면 원하는 요소값으로 채우기 가능

    - 원본 배열이 변경됨

  - Array.prototype.includes

    - ES7, 배열 내에 특정 요소 포함되어 있는지 확인하여 true/false 반환

  - Array.prototype.flat

    - ES10, 인수로 전달한 깊이만큼 재귀적으로 배열을 평탄화

    - 중첩 배열 모두 평탄화하기 위해서는 Infinity로 깊이 값 지정

27.9 배열 고차 함수

  - Array.prototype.sort

    - 배열의 요소를 정렬

    - 원본 배열 직접 변경하며 정렬된 배열 반환 (기본은 오름차순, 문자열 기준)

    - 숫자 요소 정렬 시에는 주의 필요!

      - 배열의 요소를 일시적으로 문자열로 변환한 후 유니코드 코드 포인트 순서에 따라 정렬함

      - 정렬 순서를 정의하는 비교 함수를 인수로 전달 필요 (양수, 음수, 0 반환)

      - 비교 함수의 반환값이 0보다 작으면 비교 함수의 첫 번째 인수를 우선 정렬,

        0이면 정렬 X, 0보다 크면 두 번째 인수를 우선하여 정렬

    - 프로퍼티 값 비교할 때는 - 산술 연산이 아니라 비교 연산 이용

  - Array.prototype.forEach

    - for문 대체 가능한 고차 함수

    - forEach 메서드는 forEach 메서드 호출한 원본 배열을 변경하지 않음

      - 콜백 함수를 통해 원본 배열 변경은 가능

    - forEach 메서드의 반환값은 항상 undefined

    - forEach 메서드의 두 번째 인수로 forEach 메서드의 콜백 함수 내부에서 this로 사용할 객체 전달 가능

    - forEach 메서드에 break, continue 문 사용 불가 (배열의 모든 요소를 빠짐없이 모두 순회해야 함)

    - forEach 메서드는 희소 배열의 존재하지 않는 요소를 순회 대상에서 제외

  - Array.prototype.map

    - 자신을 호출한 배열의 모든 요소 순회하면서 인수로 전달받은 콜백 함수 반복 호출

    - 콜백 함수의 반환값들로 구성된 새로운 배열 반환 (원본 배열 보존됨)

    - map 메서드가 생성하여 반환하는 새로운 배열의 length 프로퍼티 값은

      map 메서드 호출한 배열의 length 프로퍼티 값과 반드시 일치! (1:1 매핑됨)

  - Array.prototype.filter

    - 자신을 호출한 배열의 모든 요소 순회하면서 인수로 전달받은 콜백 함수 반복 호출

    - 콜백 함수의 반환값이 true인 요소로만 구성된 새로운 배열 반환 (원본 배열 보존됨)

    - filter 메서드가 생성하여 반환한 새로운 배열의 length 프로퍼티 값은

      filter 메서드를 호출한 배열의 length 프로퍼티 값과 같거나 작음

    - filter 메서드 사용하면 중복된 특정 요소 모두 제거됨

      - 특정 요소 하나만 제거하려면 indexOf 메서드와 splice 메서드 이용

  - Array.prototype.reduce

    - 자신을 호출한 배열을 모든 요소를 순회하며 인수로 전달받은 콜백 함수 반복 호출

    - 콜백 함수 반환값을 다음 순회할 때 콜백 함수의 첫 번째 인수로 전달하면서 콜백 함수 호출하여

      하나의 결과값을 만들어 반환 (원본 배열 보존됨)

      - reduce 메서드의 두 번째 매개변수로 초깃값 세팅하는 것이 안전함 (객체 프로퍼티 값 합산은 반드시 필요)

    - 평균

    - 최대값

      - Math.max(...arr)이 더 직관적

    - 요소 중복 횟수

    - 중첩 배열 평탄화

      - flat 메서드 사용하는 것이 더 직관적

    - 중복 요소 제거

      - filter 메서드 사용하는 것이 더 직관적

      - Set 자료구조와 스프레드 활용하는 것 권장

  - Array.prototype.some

    - 자신을 호출한 배열의 요소를 순회하면서 인수로 전달된 콜백 함수 호출

    - 콜백 함수의 반환값이 단 한 번이라도 참이면 true, 모두 거짓이면 false 반환

      - 빈 배열은 언제나 false 반환

  - Array.prototype.every

    - 자신을 호출한 배열의 요소 순회하면서 인수로 전달된 콜백 함수 호출

    - 콜백 함수의 반환값이 모두 참이면 true, 단 한 번이라도 거짓이면 false 반환

      - 빈 배열은 언제나 true 반환

  - Array.prototype.find

    - ES6, 자신을 호출한 배열의 요소 순회하면서 인수로 전달된 콜백함수 호출하여

      반환값이 true인 첫 번째 요소 반환

  - Array.prototype.findIndex

    - ES6, 자신을 호출한 배열의 요소 순회하면서 인수로 전달된 콜백 함수를 호출하여

      반환값이 true인 첫 번째 요소의 인덱스 반환

  - Array.prototype.flatMap

    - ES10, map 메서드를 통해 생성된 새로운 배열을 평탄화시킴 (평탄화 깊이 1단계만 가능)

    - map 메서드와 flat 메서드 순차적 실행 효과

      - 평탄화 깊이 지정 필요 시에는 map 메서드와 flat 메서드 각각 호출

반응형

댓글