알고리즘/JavaScript

JavaScript) 배열 메소드 forEach와 map 사용하기.

홍구리당당 2023. 10. 30. 19:39

0. 오늘의 배울 점

배열의 원소를 가지고 반복적인 동작을 수행할 때 보통 for of문을 자주 썼었다.

(배열에 for in 문을 쓰지 않는 이유는 아래 링크 참고..)
JavaScript로 배열 다루기 : for in 문은 배열에서 쓰지 마라?

그런데 for 문 말고, 배열 자체 메소드를 통해 반복적인 작업을 수행할 수 있다. 바로 forEach와 map 메소드 이다!!

js에서 배열을 다루는 메소드, forEach와 map을 알아보고 어떻게 활용할지 생각해보자.

참고로 배열 메소드니까 당연하게도 유사배열에서는 사용하지 못한다.

1. 배열 메소드forEach

  • 배열의 메소드로 forEach를 호출하는데, 인자로는 콜백함수를 전달해준다.
  • 이 때 콜백함수의 첫 번째 파라미터로 배열 요소를 하나씩 순서대로 받아온다. 때문에 콜백함수에는 반드시 한 개 이상의 파라미터를 두어야 한다!
    • 뿐만 아니라 콜백함수에게 두 번째 파라미터를 넘겨줄 수 있다. 이 두 번째 파라미터는 배열의 요소 인덱스를 받아온다.
    • 콜백 함수에 세 번째 파라미터도 넘겨줄 수 있다. 이 세 번째 파라미터에는 배열 그 자체가 들어간다.
  • 콜백함수로 arrow function도 쓸 수 있다.

기본적인 forEach 활용

// 기본적인 형태
{배열이름}.forEach(콜백함수(필요파라미터1, 불필요파라미터2, 불필요파라미터3){
                   //... 동작할 코드
               })

// 예시
const members = ["hellen", "john", "may", "lily", "kate"];

// 기본적인 for문
for (let ind = 0; ind < members.length; ind++){
  console.log(members[i];
}

// for of 문
for(let member of members){
  console.log(member);
}

// forEach 메소드
members.forEach((member) => {
  console.log(member);
});

forEach 문 콜백 함수에 인자 두 개 주기.

for of 문으로는 index에 접근하기 불편한 반면 forEach 메소드를 쓰면 배열의 각 요소와 해당 인덱스에 편리하게 접근할 수 있다.

또한 forEach로 인덱스 인자를 뽑아 다른 배열과 활용할 수 있다.

// forEach 메소드의 콜백함수에 인자를 두 개 넣어줄 수도 있다. 첫 번째 인자는 반드시 배열의 각 원소를 받아오는 곳이다.
members.forEach((member, ind) => {
  console.log(`${ind} 번째 손님 ${member}`);
});

// 두 개의 배열을 동시에 활용하는 예시.
const firstNames = ["kim", "park", "Lee", "Kang"];
const lastNames = ["haneul", "kangsan", "yoonji", "haeun"];

firstNames.forEach((firstName, i) => {
  console.log(`이름: ${firstName}${lastNames[i]}`);
});

forEach 문 콜백 함수에 인자 세 개 주기.

첫 번째 인자는 배열의 각 요소, 두 번째 인자는 요소의 인덱스, 그리고 세 번째 인자는 배열 그 자체가 들어간다.

잘 쓰이지 않는 인자긴 하지만, 가끔 함수 내에서 자체적으로 배열 자신을 호출할 일이 생길 때 쓴다.

const firstNames = ["kim", "park", "Lee", "Kang"];
const lastNames = ["haneul", "kangsan", "yoonji", "haeun"];

firstNames.forEach((firstName, ind, arr) => {
  console.log(`이름: ${firstName}${lastNames[i]}`);
  console.log(arr);
});

2. 배열 메소드 map

map 메소드는 나중에 리액트 코드를 짤 때에도 정말 많이 쓰이므로 잘 알아두자!!

사실 map 메소드도 사용법 자체는 forEach와 똑같다. 콜백함수를 인자로 받고, 콜백함수의 파라미터로 1~3개의 인자를 받을 수 있다는 점 모두가 같다.

그러나!! map 메소드는 forEach 메소드와 다르게 새로운 배열을 리턴해준다.

콜백 함수가 리턴해준 값들로 구성된 새로운 배열이 메소드의 결과가 된다는 것이다.

  • 그래서 forEach 때와는 다르게 map 메소드에서의 콜백 함수는 return 문을 가지고 있다.
  • map 메소드를 실행한 결과값을 담을 변수를 선언해줘야 한다.
const firstNames = ["kim", "park", "Lee", "Kang"];
const lastNames = ["haneul", "kangsan", "yoonji", "haeun"];

const fullNames = firstNames.map((firstName, ind) => {
  return(`이름: ${firstName}${lastNames[i]}`);
});

console.log(fullNames);

참고로 forEach 메소드는 리턴 값이 없기 때문에 메소드 결과를 변수에 할당해주면 undefined 값이 할당된다.

const firstNames = ["kim", "park", "Lee", "Kang"];
const lastNames = ["haneul", "kangsan", "yoonji", "haeun"];

const fullNames = firstNames.forEach((firstName, ind) => {
  return(`이름: ${firstName}${lastNames[i]}`);
});

console.log(fullNames); //undefined 출력.

3. 주의할 점.

forEach나 map 메소드의 최대 반복 횟수는 메소드를 처음 호출할 때 당시의 요소 개수이다.

예를 들어 반복문을 돌면서 요소를 새로 추가하는 코드를 짜보자.

const nums = [1,2,3,4];

nums.forEach((num) = > {
    nums.push(6);
});

console.log(nums); // [1,2,3,4,5,5,5,5];

위의 코드는 한 번씩 요소를 추가하면서 계속 요소의 수가 늘어나지만, 무한 루프에 빠지지 않고 처음 배열의 원소 개수였던 4번까지만 반복문을 돈다.

반복을 도는 도중 배열의 길이가 줄어들 때엔 반복횟수도 줄어든다.

최대 반복 횟수는 처음 배열의 원소 개수지만, 반복문을 도는 중 배열의 길이가 줄어들면 그만큼 반복 횟수도 줄어든다.

const nums = [1,2,3,4];

nums.forEach((num) = > {
    nums.pop();
});

console.log(nums); // [1,2];

요소 1에서 반복문을 돌 때 요소 4가 빠져나가고, 요소 2에서 반복문을 돌 때 요소 3이 빠져나가고, 그 다음엔 요소가 없으니 반복문이 중단된다.

4. 정리

  1. forEach와 map 함수의 콜백 함수에는 (배열요소, 배열요소의 인덱스, 배열 그 자체) 를 인자로 넣을 수 있다.
  2. forEach 문은 return 값 없이 그냥 콜백함수를 실행한다.
  3. map 문은 콜백함수가 리턴해주는 값들을 배열로 묶어 리턴해준다.
  4. 반복 횟수는 처음 배열의 원소 개수를 넘어가지 않는다.