27.1. 배열이란?
- 여러 개의 값을 순차적으로 나열한 자료 구조
- 요소 (element): 배열이 가지고 있는 값
- 자바스크립트의 모든 값을 배열의 요소가 될 수 있음
- index (인덱스): 요소는 자신의 위치를 나타내는 0 이상의 정수를 가짐
- length 프로퍼티: 배열의 길이, 요소의 개수
- 자바스크립트는 배열 타입이 존재하지 않음 -> 객체 타입
- 일반 객체와의 차이: 값의 순서, length 프로퍼티
- 처음 또는 마지막, 특정 위치부터 순차적으로 요소에 접근 가능한 장점

27.2. 자바스크립트 배열은 배열이 아니다
- 일반적인 의미의 배열은 각 요소가 동일한 데이터 크기를 가지며, 빈틈없이 연속적으로 나열된 자료구조
- 자바스크립트의 배열은 동일한 크기도 아니며 연속적이지 않은 희소 배열
- 일반적인 배열의 동작을 흉내낸 특수한 객체
- 배열의 요소는 실제로 프로퍼티의 값
- 장단점
- 일반적인 배열은 인덱스를 통해 빠르게 접근 가능하지만, 삽입 또는 삭제하는 경우 비효율적
- 자바스크립트 배열은 해시 테이블로 구현된 객체이므로 성능적으로는 느리지만, 삽입 또는 삭제하는 경우 상대적으로 빠른 성능
27.3. length 프로퍼티와 희소 배열
- length 프로퍼티: 요소의 개수 = 배열의 길이
- 빈 배열인 경우 0, 아닌 경우 가장 큰 인덱스 + 1
- 요소 추가 및 삭제 시 자동 갱신
- 명시적으로 할당 가능
- 실제 length 값보다 작은 값을 할당하면 배열의 길이가 줄어듦
- 큰 값은 할당해도 늘어나지 않음
- 아무 변화 X, 메모리 공간을 확보하거나 빈 요소를 생성하지 않음
- 희소 배열: 요소가 연속적으로 위치하지 않고 일부가 빈 배열
- 희소 배열의 length 값과 실제 요소의 개수는 일치하지 않음
- 실제 요소 개수보다 length가 항상 큼
- 성능 및 메모리 등을 위해 사용하지 않는 것을 권장
27.4. 배열 생성
27.4.1. 배열 리터럴
- 요소를 쉼표로 구분하여 대괄호([])로 묶어 표시
- 프로퍼티 키 없이 값만 존재
- 요소를 추가하지 않으면 length 0인 빈 배열 생성
- 요소를 생략하면 희소 배열 생성
27.4.2. Array 생성자 함수
- Array 생성자 함수: 전달된 인수의 개수에 따라 다른 배열 생성
- 1개의 숫자인 인수를 전달하는 경우: length = 인수인 희소 배열 생성
const arr = new Array(10);
console.log(arr);
console.log(arr.length);
- 전달된 인수가 없는 경우 빈 배열 생성 = 배열 리터럴([])
- 2개 이상의 인수나 숫자가 아닌 경우: 인수를 요소로 갖는 배열 생성
new Array(1, 2, 3);
new Array({});
- new 생략해도 생성자 함수 동작 -> new.target 확인
27.4.3. Array.of
- ES6 도입 Array.of: 전달된 인수를 요소로 갖는 배열 생성
- 전달된 인수가 1개이거나 숫자가 아니어도 생성
26.4.4. Array.from
- ES6 도입 Array.from: 유사 배열 객체 또는 이터러블 객체를 배열로 변환
- 두 번째 인수로 콜백 함수 전달 가능
Array.from({ length: 3 }, (_, i) => i);
27.5. 배열 요소의 참조
- 대괄호([]) 안에 인덱스로 배열 요소에 접근
- 존재하지 않는 요소는 undefined 반환
27.6. 배열 요소의 추가와 갱신
- 동적으로 추가 및 갱신 가능
- 존재하지 않는 인덱스로 값을 할당하면 새로운 요소 추가
- 존재하는 요소에 값을 재할당하면 요소 값 갱신
- 인덱스는 반드시 0 이상의 정수로 사용해야 함
- 정수 이외의 값을 사용하면 프로퍼티가 생성됨
- length 값에 영향 없음
27.7. 배열 요소의 삭제
- 자바스크립트 배열은 객체이므로 delete 연산자 사용 가능
- delete 사용 시 희소 배열이 됨 -> 사용 권장 X
- Array.prototype.splice (삭제 시작 인덱스, 삭제할 요소 수) 권장
27.8. 배열 메서드
- 원본 배열을 변경하는 메서드
- 원본 배열을 변경하지 않고 새로운 배열을 반환하는 메서드
27.8.1. Array.prototype.isArray
- 배열 여부 판별
- 전달된 인수가 배열이면 true, 아니면 false
27.8.2. Array.prototype.indexOf
- 인수로 전달된 요소를 검색하여 인덱스 반환
- 중복되는 요소가 있다면 첫 번째 요소의 인덱스 반환
- 존재하지 않으면 -1 반환
- 특정 요소의 존재 여부 판별 시 사용
27.8.3. Array.prototype.push
- 인수로 전달받은 모든 값을 마지막 요소로 추가 후 변경된 length 반환
- 원본 배열 변경
- 성능 면에서 좋지 않으므로 권장 X
- 추가할 요소가 하나라면 length 권장
- ES6 스프레드 문법 권장
const arr = [1, 2];
arr[arr.length] = 3;
console.log(arr);
const newArr = [...arr, 3];
console.log(newArr);
27.8.4. Array.prototype.pop
- 마지막 요소를 제거하고 제거한 요소를 반환
- 원본 배열 변경
- push와 함께 스택(stack, LIFO) 구현 가능
27.8.5. Array.prototype.unshift
- 인수로 전달받은 모든 값을 배열의 선두 요소로 추가 후 변경된 length 값 반환
- 원본 배열 변경
27.8.6. Array.prototype.shift
- 첫 번째 요소를 제거하고 제거한 요소 반환
- 원본 배열 변경
- push와 함께 큐(queue, FIFO) 구현 가능
27.8.7. Array.prototype.concat
- 인수로 전달된 값을 배열의 마지막 요소로 추가한 다음 새로운 배열 반환
- 배열을 전달받는 경우 원본 배열을 해체하여 새로운 배열의 요소로 추가함
- 원본 배열은 변경하지 않음
- push, unshift 대체 가능
[앞에 추가할 요소].concat([뒤에 추가할 요소])
- ES6 스프레드 문법으로도 대체 가능 -> 사용 권장
27.8.8. Array.prototype.splice
- 배열의 중간에 요소를 추가하거나 제거 가능
- start: 제거를 시작할 인덱스
- deleteCount: start부터 제거할 요소의 개수
- items: 제거한 위치에 삽입할 요소들의 목록
- 원본 배열 변경
- indexOf와 함께 제거하려는 특정 요소의 인덱스를 얻어 제거 가능
- filter 메서드로도 가능 -> 중복 요소 모두 제거됨
27.8.9. Array.prototype.slice
- 전달된 범위의 요소들을 복사하여 배열로 반환
- start: 복사를 시작할 인덱스, 음수의 경우 뒤에서부터
- end: 이전 인덱스까지 복사 후 종료(미포함), 생략 시 length 프로퍼티 값
- 모두 생략 시 원본 배열의 전체 복사본 반환 -> 얕은 복사
- 원본 배열은 변경하지 않음
- arguments, HTMLCollections, NodeList 등 유사 배열 객체를 배열로 변환
27.8.10. Array.prototype.join
- 모든 요소를 문자열로 변환 후 인수로 전달받은 문자(구분자)로 연결한 문자열 반환
const arr = [1, 2, 3, 4];
arr.join();
arr.join('');
arr.join(':');
27.8.11. Array.prototype.reverse
- 원본 배열의 순서를 반대로 변경하여 반환
- 원본 배열 변경
27.8.12. Array.prototype.fill
- ES6 도입: 배열의 모든 값을 인수로 전달받은 값으로 변경
- 두 번째 인수로 시작할 인덱스 전달 가능
- 세 번째 인수로 멈출 인덱스 전달 가능
- 원본 배열 변경
- 모든 요소를 하나의 값으로만 변경 가능
27.8.13. Array.prototype.includes
- ES7 도입: 특정 요소가 포함되었는 지 판별하여 boolean 반환
- 첫 번째 인수로 검색할 요소(대상) 지정
- 두 번재 인수로 검색을 시작할 인덱스 지정 가능, 생략 시 처음부터(0)
- indexOf보다 가독성이 좋음, 추가 판별이 필요 없음
27.8.14. Array.prototype.flat
- ES10 도입: 인수로 전달한 깊이만큼 재귀적으로 배열을 평탄화
- 인수 생략하면 기본값 1
- Infinity 전달하면 모든 중첩 배열을 평탄화
[1, [2, [3, [4]]]].flat();
[1, [2, [3, [4]]]].flat(2);
[1, [2, [3, [4]]]].flat(Infinity);
27.9. 배열 고차 함수
- 고차 함수(HOF): 함수를 인수로 전달받거나 함수를 반환하는 함수
- 불변성을 지향하는 함수형 프로그래밍 기반
- 조건문과 반복문을 제거하여 복잡성 해결
- 변수의 사용을 억제하여 상태 변경을 피함
- 순수 함수를 통해 부수 효과를 최대한 억제하고 안정성을 높이고자 함
27.9.1. Array.prototype.sort
- 배열의 요소 정렬하여 반환
- 원본 배열 변경
- 기본적으로 오름차순
- 내림차순으로 정렬하려면 sort + reverse
- 정렬 순서는 유니코드 코드 포인트의 순서 (문자열로 변환하여 정렬)
- 숫자를 정렬할 때는 비교 함수를 인수로 전달해야 함
- 비교 함수의 반환값이 0보다 작으면 첫 번째 우선 정렬, 크면 두 번째 우선 정렬
const point = [40, 100, 1, 5, 2, 25, 10];
points.sort((a, b) => a - b);
console.log(points)
points.sort((a, b) => b - a);
console.log(points)
- ES10부터 timsort 알고리즘으로 변경됨
27.9.2. Array.prototype.forEach
- 자신의 내부에서 반복문을 실행하는 메서드
- 원본 배열은 변경하지 않음
- 호출한 배열의 요소값과 인덱스, 배열 자체(this) 전달 가능
- 화살표 함수를 사용하면 상위 스코프의 this 그대로 참조 가능
- 항상 undefined 반환
- break, continue 사용 불가
27.9.3. Array.prototype.map
- 자신을 호출한 배열의 모든 요소를 순회하면서 콜백 함수를 반복 호출
- 원본 배열은 변경하지 않음
- 콜백 함수들의 반환값으로 구성된 새로운 배열 반환
- 새로운 배열의 length === 호출한 배열의 length (1:1)
- 반환값 외에 forEach와 유사함
27.9.4. Array.prototype.filter
- 모든 요소를 순회하면서 콜백 함수의 반환값이 true인 요소로 구성된 새로운 배열 반환
- 새로운 배열의 length <= 호출한 배열의 length
- 원본 배열은 변경하지 않음
- 반환값 외에 forEach, map과 유사함
- 특정 요소 하나만 제거하려면 splice 사용
27.9.5. Array.prototype.reduce
- 모든 요소를 순회하며 콜백 함수의 반환값을 다음 콜백 함수의 첫 번째 인수로 전달 후 하나의 결과값으로 반환
- 두 번째 인수로 초기값 전달 가능 -> 생략 가능하지만 전달하는 것을 권장
- 원본 배열은 변경하지 않음
- 자신을 호출한 배열의 모든 요소를 순회하며 하나의 누적된 결과값을 필요한 경우 사용
- 평균, 최대값, 요소의 중복 횟수, 중첩 배열 평탄화, 중복 요소 제거 등
const values = [1, 2, 3, 4, 5, 6];
const average = values.reduce(
(acc, cur, i, { length }) => {
return i === length - 1
? (acc + cur) / length
: acc + cur;
}, 0);
console.log(average);
27.9.6. Array.prototype.some
- 모든 요소를 순회하며 콜백 함수의 반환값이 한 번이라도 참이면 true, 아니면 false 반환
- 콜백 함수를 통해 정의한 조건을 만족하는 요소가 1개 이상 존재하는지 확인
- 빈 배열인 경우 항상 false 반환
27.9.7. Array.prototype.every
- 모든 요소를 순회하며 콜백 함수의 반환값이 모두 참이면 true, 아니면 false 반환
- 모든 요소가 정의한 조건을 모두 만족하는지 확인
- 빈 배열인 경우 항상 true 반환
27.9.8. Array.prototype.find
- ES6 도입: 모든 요소를 순회하며 콜백 함수의 반환값이 true인 첫 번째 요소 반환
- 존재하지 않는다면 undefined 반환
- find의 결과값은 배열이 아닌 해당 요소값
27.9.9. Array.prototype.findIndex
- ES6 도입: 모든 요소를 순회하며 콜백 함수의 반환값이 true인 첫 번째 요소의 인덱스 반환
- 존재하지 않는다면 -1 반환
27.9.10. Array.prototype.flatMap
- ES10 도입: map을 통해 생성된 새로운 배열을 평탄화
- map + flat 순차적으로 실행하는 기능
- 단, 평탄화 깊이는 지정할 수 없이 1단계만 가능
- 지정이 필요한 경우 map().flat() 각각 호출
[출처] 모던 자바스크립트, Deep Dive