앞서 자바스크립트의 배열은 일반 객체에 기능을 추가해 만든 특수한 객체라고 하였습니다.따라서 자바스크립트는 배열을 쉽게 다룰 수 있도록 여러 메서드를 제공합니다. 이런 메서드를 ‘배열 메서드’라고 합니다. 배열 메서드는 실무에서 자주 사용하므로 종류와 사용 방법을 잘 익혀두는 게 좋습니다. 이번 절에서는 자주 쓰는 배열 메서드를 직접 실습하면서 익혀보겠습니다.
요소의 추가 및 삭제 메서드
배열 요소란 배열에 담긴 하나의 값입니다. 배열은 여러 개의 값을 동적으로 저장합니다. 이번 단원에서는 배열 요소를 자유롭게 추가, 수정, 삭제할 수 있는 배열 메서드에 대해 알아봅니다.
push
push는 배열 맨 끝에 요소를 추가하고 새로운 길이를 반환하는 메서드입니다.
코드를 불러오는 중 입니다 ...① push 메서드를 호출하고 인수로 추가하려는 요소를 전달합니다.
콘솔의 결과를 보면 새로운 요소가 배열 맨 끝에 추가되고, 새로운 배열의 길이로 4를 반환합니다.
push 메서드로 여러 요소를 추가하려면 콤마로 구분해 전달하면 됩니다.
코드를 불러오는 중 입니다 ...push 메서드로 콤마로 구분한 두 개의 인수, “탕수육”과 “라자냐”를 전달해 배열에 추가했습니다. push 메서드는 무조건 배열 맨 끝에 요소를 추가합니다. 배열 중간이나 맨 앞에 요소를 추가하려면 다른 메서드를 사용해야 합니다.
pop
pop은 배열의 맨 끝 요소를 제거하고, 제거한 요소를 반환하는 메서드입니다.
코드를 불러오는 중 입니다 ...① pop 메서드를 호출해 배열 food의 맨 끝 요소인 "치킨"을 제거합니다. pop 메서드는 제거한 값을 반환하므로 removedItem에는 "치킨"이 저장됩니다.
빈 배열에서 pop 메서드를 사용하면, 제거할 요소가 없기 때문에 undefined를 반환합니다.
코드를 불러오는 중 입니다 ...shift
shift는 pop 메서드와 반대로 배열의 맨 앞 요소를 제거하고, 제거한 요소를 반환하는 메서드입니다.
코드를 불러오는 중 입니다 ...① shift 메서드를 호출해 배열 food의 맨 앞 요소인 "짜장면"을 제거합니다. shift 메서드는 제거 한 값을 반환하므로 removedItem에는 "짜장면"이 저장됩니다.
unshift
unshift는 push와 반대로 배열 맨 앞에 요소를 추가하고, 새 배열의 길이를 반환하는 메서드입니다.
코드를 불러오는 중 입니다 ...① unshift 메서드를 호출하고 인수로 추가하려는 요소를 전달합니다.
콘솔의 결과를 보면, 배열 맨 앞에 갈비찜이 추가되고 새로운 배열의 길이로 4가 반환됩니다.
unshift 메서드로 배열 맨 앞에 여러 요소를 추가하려면, push와 마찬가지로 요소를 콤마로 구분해 전달하면 됩니다.
shift와 unshift는 느립니다
배열은 여러 요소를 순서대로 저장하는 자료구조이며, 0부터 시작하는 인덱스로 배열 요소에 접근합니다. 이 규칙은 배열에서 반드시 유지되어야 할 원칙입니다.
unshift 메서드로 배열 맨 앞에 요소를 추가하면, 새 요소가 인덱스 0이 되어 나머지 배열 요소의 인덱스는 모두 하나씩 뒤로 밀립니다.
또한 shift 메서드로 0번 인덱스 요소를 제거하면, 기존 요소의 인덱스는 모두 하나씩 앞으로 당겨져야 합니다.
반면 push나 pop 메서드는 배열의 마지막 요소를 추가 또는 제거하는 것이므로 기존 요소들의 인덱스는 변함이 없습니다. 따라서 이들 메서드가 shift나 unshift보다 성능이 더 좋습니다.
slice
slice 메서드는 마치 가위처럼 기존 배열에서 특정 범위를 잘라 새로운 배열을 반환합니다. 이때 원본 배열은 수정되지 않는다는 점에 유의합니다. 문법은 다음과같습니다.
코드를 불러오는 중 입니다 ...slice 메서드에서는 잘라내려는 배열의 범위를 지정하는 두 개의 인수를 전달합니다. start는 잘라낼 범위의 시작, end는 잘라낼 범위의 끝을 지정하는 인덱스입니다. 다만 한 가지 주의할 점은 end로 범위의 끝을 지정하면, 그 범위는 end 인덱스 전까지입니다.
코드를 불러오는 중 입니다 ...① slice 메서드에서 start를 0, end를 2로 하여 인수를 전달합니다. 따라서 배열 arr의 0번에서 1번 인덱스까지 잘라 새로운 배열을 반환합니다.
출력 결과를 보면 기존 배열(arr)은 수정되지 않는다는 것을 알 수 있습니다.
slice 메서드에서 start만 전달하고 end를 전달하지 않으면, start부터 배열 끝까지 잘라낸 새 배열을 반환합니다.
코드를 불러오는 중 입니다 ...① slice 메서드에 start로 2만 전달했으므로 2번 인덱스부터 배열 맨 끝까지 잘라낸 새 배열을 반환합니다.
음숫값을 인덱스로 전달해도 됩니다. 만약 end 없이 start만 음수 인덱스로 전달하면, 배열 맨 끝부터 전달한 음수의 절댓값만큼 잘라낸 새 배열을 반환합니다.
코드를 불러오는 중 입니다 ...① 음숫값을 인덱스로 전달해 배열의 맨 끝부터 음수의 절댓값 만큼 잘라낸 배열을 반환합니다. 인덱스 번호는 기본적으로 0에서 시작하지만, 뒤에서부터 셀 때는 -1이 첫 번째 인덱스 번호입니다.
concat
concat은 서로 다른 배열을 이어 붙여 새 배열을 반환하는 메서드입니다.
코드를 불러오는 중 입니다 ...① 배열 arrA에서 concat 메서드를 호출하고 인수로 배열 arrB를 전달합니다. 결과는 arrA 뒤에 arrB를 이어 붙인 새 배열을 반환합니다. ② concat 메서드는 앞서 살펴본 slice 메서드처럼 원본 배열을 수정하지 않습니다.
이번에는 concat 메서드에 인수로 배열이 아닌 객체를 전달합니다.
코드를 불러오는 중 입니다 ...concat 메서드에서 인수로 배열을 전달하면 요소를 모두 이어 붙이지만, 객체는 하나의 요소로 인식해 삽입됩니다.
제 콘솔에는 object로 표시됩니다.
코드샌드박스의 콘솔에서는 객체가 object로 표시됩니다. 왼쪽에 있는 삼각형(▶) 표시 를 클릭하면 객체의 요소를 펼 쳐볼 수 있습니다.
순회 메서드
일반적으로 배열을 순회할 때는 앞서 살펴본 반복문을 많이 이용합니다. 그러나 자바스크립트는 반복문 말고도 배열 순회 메서드를 제공합니다. 이 책에서는 순회 메서드 가운데 자주 사용하는 forEach의 사용법을 알아보겠습니다.
forEach는 배열의 모든 요소에 순서대로 접근해 특정 동작을 수행하는 메서드입니다. forEach 메서드의 문법은 다음과 같습니다.
코드를 불러오는 중 입니다 ...forEach는 인수로 함수를 요구하는 메서드입니다. 함수 호출 과정에서 인수로 전달되는 함수를 ‘콜백 함수’라고 했습니다. forEach 메서드는 배열 요소 각각을 순회하면서, 인수로 전달한 콜백 함수가 정의한 대로 요소를 동작 시킵니다. 이 콜백 함수에는 3개의 매개변수가 제공됩니다.
- item: 현재 순회하는 배열 요소
- idx: 현재 순회하는 배열 요소의 인덱스
- arr: 순회 중인 배열
다음은 forEach 메서드로 모든 배열 요소를 인덱스와 함께 출력하는 예입니다.
코드를 불러오는 중 입니다 ...① 배열 arr에서 forEach 메서드를 호출하고 인수로 함수 cb를 전달합니다. ② forEach 메서드의 콜백 함수로 전달된 함수 cb는 각각의 배열 요소에 대해 정의한 동작을 수행합니다.
배열 arr의 모든 요소에 대해 함수 cb를 실행합니다. 그 결과 함수 cb는 총 3번 실행되는데, 그때마다 인덱스와 배열 요소가 순서대로 매개변수로 저장되고 값을 콘솔에 출력합니다.
forEach로 전달되는 콜백 함수는 함수 표현식이나 화살표 함수로 간략하게 표현 할 수 있습니다.
코드를 불러오는 중 입니다 ...① forEach 메서드를 호출하면서 인수로 화살표 함수를 생성해 전달합니다.
화살표 함수는 앞선 예제의 함수 cb와 동일한 역할을 합니다. 따라서 배열 arr의 모
든 요소에 대해 한 번씩 실행됩니다.
탐색 메서드
배열 탐색이란 배열에서 특정 조건을 만족하는 요소를 찾아내는 행위입니다. 탐색 메서드를 활용하면 간단하게 배열에서 특정 요소를 검색할 수 있습니다.
indexOf
indexOf는 배열에서 찾으려는 요소의 인덱스를 반환하는 메서드입니다. indexOf 메서드는 두 개의 인수를 전달하며 문법은 다음과 같습니다.
코드를 불러오는 중 입니다 ...item은 찾으려는 요솟값, fromIndex는 탐색을 시작할 인덱스 번호입니다.
코드를 불러오는 중 입니다 ...① 배열 arr에서 indexOf 메서드를 호출하고, 인수로 찾으려는 값 1, 탐색을 시작할 인덱스 번호 0을 전달합니다. 따라서 탐색 시작 인덱스 0부터 1씩 늘려가며 검색하는데, 찾으려는 값이 첫 번째에 있으므로 인덱스 번호 0을 반환합니다.
두 번째 인수인 fromIndex는 생략할 수 있습니다. 생략하면 배열의 0번째 인덱스부터 탐색합니다. 또한 fromIndex의 값을 음수로 지정할 수 있는데, 그러면 탐색 위치는 배열의 맨 뒤에서부터 시작합니다. 예를 들어 위 예제에서 fromIndex를 -1로 전달하면 4번 인덱스부터 탐색을 시작합니다
코드를 불러오는 중 입니다 ...① fromIndex를 생략하면 0번 인덱스부터 탐색합니다. 그 결과 가장 가까운 곳에 있는 요소1의 인덱스 번호 0을 반환합니다 ② 두 번째 인수 fromIndex를 음수로 전달하면, 배열의 맨 끝에서부터 전달한 음수의 절대값만큼 앞으로 이동한 위치부터 탐색을 시작합니다
찾으려는 요소가 배열에 없다면 -1을 반환합니다.
코드를 불러오는 중 입니다 ...① 배열 arr에 값이 4인 요소가 없으므로 탐색에 실패하여 -1을 반환합니다.
두 번째 인수 fromIndex의 값이 배열의 길이보다 크거나 같은 경우에도 -1을 반환합니다.
코드를 불러오는 중 입니다 ...① 배열 arr의 마지막 인덱스 번호는 4이므로 9번 인덱스 번호에서 탐색하는 것은 불가능합니다. 따라서 탐색에 실패하여 -1을 반환합니다.
indexOf는 엄격한 비교 연산자(===)로 요소를 비교하므로 자료형이 다르면 다른 값으로 평가합니다.
코드를 불러오는 중 입니다 ...배열 arr에는 숫자형 3은 존재하지만, 문자형 "3"은 존재하지 않습니다. 따라서 탐색에 실패하며 -1을 반환합니다.
indexOf는 ===로 값을 비교하기 때문에 특정 조건을 만족하는 객체를 탐색할 수 없습니다. 앞서 살펴보았듯이 객체 자료형은 값을 비교하는 게 아니라 참좃값을 비교하기 때문입니다.
코드를 불러오는 중 입니다 ...찾으려는 값으로 객체를 인수로 전달합니다. 동일한 프로퍼티를 가진 객체가 배열 arr에 있지만, 객체 간에는 참좃값을 비교하기 때문에 탐색에 실패하며 -1을 반환합니다.
indexOf 메서드로는 객체 자료형의 값을 탐색할 수 없습니다. 이를 위해서는 findIndex와 같은 다른 메서드를 사용해야 하는데 이는 뒤에서 살펴보겠습니다.
includes
includes 메서드는 배열에 특정 요소가 있는지 판별합니다. 문법은 다음과 같습니다.
코드를 불러오는 중 입니다 ...includes 메서드는 indexOf처럼 item과 fromIndex를 인수로 전달하며 사용법도 같습니다.
코드를 불러오는 중 입니다 ...includes 메서드는 인수로 전달한 요소가 배열에 존재하면 true, 그렇지 않으면 false를 반환합니다. indexOf는 탐색에 성공하면 해당 요소의 인덱스 번호를 반환하지만, includes는 불리언 값 true를 반환합니다.
findIndex
findIndex 메서드는 indexOf처럼 배열에서 찾으려는 요소의 인덱스 번호를 찾아 반환합니다. 문법은 다음과 같습니다.
코드를 불러오는 중 입니다 ...findIndex는 indexOf와는 달리 인수로 콜백 함수를 전달하는데, 이 함수를 ‘판별 함수’라고 합니다. 배열에서 이 판별 함수를 만족하는 첫 번째 요소의 인덱스를 반환하며, 그런 요소가 없다면 -1을 반환합니다. 판별 함수에는 3개의 매개변수(현재요소 item, 현재 인덱스 index, 탐색 대상 배열 array)가 제공되며, 이 변수로 판별식을 만듭니다.
코드를 불러오는 중 입니다 ...① findIndex 메서드를 호출하고 인수로 판별 함수 determine을 전달합니다. ② 판별 함수 determine은 item이 짝수면 true를 반환하고, 그렇지 않으면 false를 반환합니다.
판별 함수 determine은 배열 arr 각 요소에 대해 순차적으로 실행하며 판별 결과를 true나 false로 반환합니다. findIndex 메서드가 true를 반환하면 탐색에 성공한 것이므로 탐색을 멈춥니다. 이때 findIndex는 탐색을 멈춘 인덱스 번호를 반환합니다. 결과는 배열 arr에서 처음으로 짝숫값이 나오는 인덱스 번호 3을 반환합니다.
화살표 함수와 삼항 연산자를 이용하면 코드를 더 간결하게 만들 수 있습니다.
코드를 불러오는 중 입니다 ...실무에서는 화살표 함수와 삼항 연산자를 이용해 함수를 간결하게 작성하는 경우가 많으니 이런 문법에 익숙해져야 합니다.
이번에는 findIndex로 배열에서 프로퍼티 name의 값이 “이정환”인 요소의 인덱스 번호를 찾아보겠습니다.
코드를 불러오는 중 입니다 ...① findIndex에서 name 프로퍼티의 값이 "이정환"인 요소를 찾는 판별 함수를 직접 인수로 전달합니다. true를 반환하는 요소의 인덱스 번호를 index에 저장합니다.
indexOf는 엄격한 비교 연산자 ‘===’를 사용하므로 객체 자료형을 찾아내기 어렵지만, findIndex는 판별 함수를 이용해 배열에서 조건과 일치하는 객체 요소를 찾아냅니다.
find
find 메서드는 findIndex처럼 인수로 판별 함수를 전달하고, 배열에서 이를 만족하는 요소를 찾습니다. find는 findIndex와는 달리 인덱스가 아닌 요소를 반환합니다.
코드를 불러오는 중 입니다 ...① 배열 arr에서 name 프로퍼티의 값이 “이정환”인 요소를 찾아 변수 element에 저장합니다.
find 메서드는 배열에서 특정 조건을 만족하는 요소를 찾을 때 유용하게 사용합니다.
filter
filter 메서드는 배열에서 조건을 만족하는 요소만 모아 새로운 배열로 반환하는 메서드입니다. 문법은 find, findIndex 메서드와 거의 비슷합니다.
코드를 불러오는 중 입니다 ...filter 메서드로 다음 객체 배열에서 취미가 ‘축구’인 사람을 모두 찾아 새로운 배열로 반환하겠습니다.
코드를 불러오는 중 입니다 ...① 배열 arr의 요소 중 hobby 프로퍼티의 값이 "축구"인 요소만 모아 새로운 배열로 만들어 filteredArr에 저장합니다.
지금까지 5가지 배열 탐색 메서드를 알아보았습니다. 배열 탐색 메서드는 검색, 카테고리, 필터링 등 여러 상황에서 매우 유용하게 사용합니다.
변형 메서드
배열을 변형하거나 요소를 재정렬하는 메서드인 배열 변형 메서드를 살펴보겠습니다.
map
map은 배열 각각의 요소에 대한 함수 호출 결과를 모아 새 배열을 만들어 반환하는 메서드입니다. 문법은 다음과 같습니다.
코드를 불러오는 중 입니다 ...map 메서드는 콜백 함수를 인수로 전달합니다. 이 콜백 함수에는 현재 요소 item, 인덱스 index, map 메서드를 호출한 배열 array이 매개변수로 제공됩니다.
map 메서드로 배열의 모든 요소에 3을 곱해 얻은 값을 새 배열로 만들겠습니다.
코드를 불러오는 중 입니다 ...① 배열 arr의 모든 요소에 대해 콜백 함수를 실행합니다. 콜백 함수는 매개변수로 제공된 배열 요소에 3을 곱해 반환하므로, 새롭게 만든 newArr에는 배열 arr의 모든 요소에 3을 곱한 결과가 저장 됩니다.
이번에는 map 메서드로 객체를 저장하는 배열을 다른 형태로 구성하겠습니다.
코드를 불러오는 중 입니다 ...① map 메서드의 인수로 전달한 콜백 함수는 각 요소의 name 프로퍼티 값을 반환합니다. 결과적으로 newArr에는 기존 arr에서 사람 이름만 따로 모은 배열이 저장됩니다.
map 메서드는 이렇게 배열을 새로운 형태로 바꿀 수 있기 때문에 활용도가 매우 높습니다. 앞으로 자주 사용하게 되니 꼭 기억하길 바랍니다.
sort
sort는 배열의 요소를 정렬할 때 사용하는 메서드입니다. 문법은 다음과 같습니다.
코드를 불러오는 중 입니다 ...sort 메서드에서는 하나의 콜백 함수를 인수로 전달합니다. 이 함수는 비교 함수로 사용되는데, 필수 사항은 아닙니다. 비교 함수를 생략하면 사전 순, 오름차순으로 정렬합니다.
코드를 불러오는 중 입니다 ...sort 메서드로 문자로 이루어진 배열 arr을 사전 순, 오름차순으로 정렬했습니다.
여기서 한 가지 중요한 사실이 있는데, sort 메서드는 기존 배열 자체를 정렬한다는 겁니다. 다시 말해 정렬된 새로운 배열을 반환하는 게 아니라, 기존 배열 요소를 다시 정렬한다는 점에 주의하길 바랍니다.
이번에는 문자가 아닌 숫자로 이루어진 배열을 sort 메서드로 정렬합니다.
코드를 불러오는 중 입니다 ...무언가 결과가 이상합니다. 오름차순으로 정렬한 것도 아니고, 내림차순으로 정렬한 것도 아닙니다. 이것은 sort 메서드가 기본적으로 요소를 문자열로 취급해 사전순으로 정렬하기 때문입니다.
이때 비교 함수가 필요합니다. 비교 함수는 배열 요소 두 개를 인수로 전달하는데, 이 함수의 반환값에 따라 정렬 방식이 달라집니다.
- 비교 함수가 양수를 반환
a와 b 중 b의 위치가 a보다 앞이어야 한다는 것을 의미.
- 비교 함수가 음수를 반환
a와 b 중 a의 위치가 b보다 앞이어야 한다는 것을 의미.
- 비교 함수가 0을 반환
비교 함수가 0을 반환하면, a와 b는 정렬 순서가 동일하다는 것을 의미.
이번에는 비교 함수를 이용해 오름차순으로 배열을 정렬하겠습니다.
코드를 불러오는 중 입니다 ...비교 함수를 자세히 살펴보면, 다음과 같은 방식으로 동작합니다.
- a가 b보다 클 때
a가 b보다 크면 양수 1을 반환하며, a는 b의 뒤로 갑니다.
- a가 b보다 작을 때
a가 b보다 작으면 음수 -1을 반환하며, a는 b의 앞으로 갑니다.
- a와 b가 같을 때
a와 b가 같다면 자리를 바꾸지 않습니다.
정리하면 a는 b보다 크면 뒤로 가고 작으면 앞으로 옵니다. 따라서 배열의 모든 요소에 대해 비교 함수를 실행하면 배열은 오름차순으로 정렬됩니다. sort 메서드는 비교 함수를 이용해 대부분의 정렬을 수행합니다.
join
join 메서드는 배열 요소를 모두 연결해 하나의 문자열로 반환합니다. 문법은 다음과 같습니다.
코드를 불러오는 중 입니다 ...join 메서드에는 분리 기호로 사용하는 구분자(separator)를 인수로 전달하는데, 이는 필수 사항은 아닙니다. 구분자는 배열 요소를 합칠 때 각각의 요소를 구분하는 문자열이며, 생략하면 콤마(,)를 기본값으로 제공합니다.
코드를 불러오는 중 입니다 ...① 구분자를 생략했으므로, 각 요소는 콤마로 구분합니다. ② 구분자 "-"를 각 요소를 구분하기 위해 사용합니다.
reduce
reduce는 배열 요소를 모두 순회하면서 인수로 제공한 함수를 실행하고, 단 하나의 결괏값만 반환하는 메서드입니다. map 메서드와 유사하지만 하나의 결과만을 반환한다는 차이가 있습니다.
코드를 불러오는 중 입니다 ...reduce 메서드는 호출할 때 2개의 인수를 전달합니다. 첫 번째 인수로 콜백 함수를 전달하며, 두 번째 인수로는 initial(초깃값)을 전달합니다.
reduce 메서드의 첫 번째 인수로 전달하는 콜백 함수를 특별히 ‘리듀서’라고 부릅니다. 이 리듀서 함수는 map이나 forEach 메서드가 전달하는 콜백 함수처럼 배열의 모든 요소에 대해 각각 실행되는데, 4개의 매개변수를 제공받습니다.
리듀서에 제공되는 매개변수의 역할은 다음과 같습니다.
- acc: 누산기(accumulator)라는 뜻으로 이전 함수의 호출 결과를 저장합니다.
reduce 메서드의 두 번째 인수 initial이 이 acc의 초깃값이 됩니다.
- item: 현재의 배열 요소입니다.
- index: 현재의 배열 인덱스입니다.
- array: reduce 메서드를 호출한 배열입니다.
acc의 초깃값인 인수 initial은 필수 사항은 아니며, 전달하지 않으면 배열의 첫 번째 요소가 acc의 초깃값이 됩니다. reduce 메서드를 이용하면 코드 한 줄로 배열 모든 요소의 누적값을 구할 수 있습니다.
코드를 불러오는 중 입니다 ...이 코드에서 reduce 메서드에 전달한 첫 번째 인수인 리듀서는 누산기인 acc와 현재의 배열 요소인 item, 2개의 매개변수만 제공받습니다. 리듀서는 배열 요소의 개수만큼 5번 실행됩니다. 동작 과정을 자세히 살펴보면 다음과 같습니다
- 반복 1 reduce 메서드에서 initial로 0을 전달했으므로, acc의 초깃값은 0입니다. 첫 번 째로 접근하는 배열 요소 item의 값은 1이므로 0+1을 반환합니다.
- 반복 2 현재 acc는 반복 1의 리듀서 함수가 반환한 결과인 0+1이며, item은 2입니다. 따 라서 0+1+2를 반환합니다.
- 반복 3 현재 acc는 반복 2의 리듀서 함수가 반환한 결과인 0+1+2이며, item은 3입니다. 따라서 0+1+2+3을 반환합니다
- 반복 4 현재 acc는 반복 3의 리듀서 함수가 반환한 결과인 0+1+2+3이며, item은 4입니 다. 따라서 0+1+2+3+4를 반환합니다
- 반복 5 현재 acc는 반복 4의 리듀서 함수가 반환한 결과인 0+1+2+3+4이며, item은 5입니 다. 따라서 0+1+2+3+4+5를 반환합니다
reducer 메서드의 호출 결과는 마지막으로 반복했을 때의 acc 값입니다. 따라서 redcuer의 호출 결과는 0+1+2+3+4+5인 15가 됩니다.