Front-End/JavaScript

[JavaScript] forEach, map 배열 메소드

시니철 2024. 9. 13. 17:29

forEach 배열 메소드

forEach와 map 배열 메소드를 확인하기 전에 for...of문을 forEach배열 메소드와 비교해보려고 한다.

// for...of문
const members = ['휘철', '은주', '꿈', '달'];

for (let member of members) {
  console.log(`${member}`);
}
// 휘철
// 은주
// 꿈
// 달
// forEach 배열 메소드
members.forEach(function (member) {
  console.log(`${member}`);
})


// 화살표 함수 사용 예시
members.forEach((member) => {
  console.log(`${member}`);
})

 

위처럼 for...of문을 forEach 배열 메소드로 코드를 작성할수도 있고, 추가적으로 2가지 파라미터를 더 다룰 수 있다.

 

추가적으로 활용할 수 있는 두 번째 파라미터는 index, 세 번째 파라미터는 반복 중인 배열 자체를 파라미터에 담아서 출력할 수 있다.

// 두 번째 파라미터 index 사용 예시
const members = ['휘철', '은주', '꿈', '달'];

members.forEach((member, index) => {
  console.log(`${index}, ${member}`);
})
// 0번, 휘철
// 1번, 은주
// 2번, 꿈
// 3번, 달


// index 파라미터를 활용한 예시
const firstNames = ['휘철', '은주', '꿈', '달'];
const lastNames = ['신', '정', '김', '정'];

firstNames.forEach(function (firstName, i) {
  console.log(`${lastNames[i]}${firstName}!!`);
})
// 신휘철!!
// 정은주!!
// 김꿈!!
// 정달!!
// 세 번째 파라미터 반복 중인 배열 출력
const firstNames = ['휘철', '은주', '꿈', '달'];
const lastNames = ['신', '정', '김', '정'];

firstNames.forEach(function (firstName, i, arr) {
  console.log(`${lastNames[i]}${firstName}!!`);
  console.log(arr);
})

// 신휘철!!
// ['휘철', '은주', '꿈', '달']
// 정은주!!
// ['휘철', '은주', '꿈', '달']
// 꿈!!
// ['휘철', '은주', '꿈', '달']
// 달!!
// ['휘철', '은주', '꿈', '달']

 

추가로 for...of  break ,contenue 같은 제어문을 사용할 수 있지만, forEach는 제어문을 사용할 수 없다.

 


map 배열 메소드

map 메소드는 forEach 메소드를 사용하는 방식과 거의 비슷하고 같은 결과 값이 나오지만 map 메소드는 새로운 배열을 만들어서 리턴한다는 특징이 있다.

const firstNames = ['휘철', '은주', '꿈', '달'];
const lastNames = ['신', '정', '김', '정'];

firstNames.map(function (firstName, i, arr) {
  console.log(`${lastNames[i]}${firstName}!!`);
  console.log(arr);
})

// 신휘철!!
// ['휘철', '은주', '꿈', '달']
// 정은주!!
// ['휘철', '은주', '꿈', '달']
// 꿈!!
// ['휘철', '은주', '꿈', '달']
// 달!!
// ['휘철', '은주', '꿈', '달']

 

위 소스는 forEach문에서 세 번째 파라미터 설명했던 코드 그대로 가져와 map 배열 메소드로만 바꿔준 소스 코드이고 같은 콘손 값을 확인할 수 있다.

// 새 배열을 반환하고 그 배열을 fullName에 저장
const firstNames = ['휘철', '은주', '꿈', '달'];
const lastNames = ['신', '정', '김', '정'];

const fullName = firstNames.map(function(firstName, i) {
  return lastNames[i] + firstName;
})

// 화살표 문법으로 간결하게도 작성 가능
const fullName = firstNames.map((firstName, i) => lastNames[i] + firstName);

console.log(fullName);
// ['신휘철', '정은주', '김꿈', '정달']

 

참고로 forEach 메소드는 리턴 값이 없기 때문에 변수에 담았을 때 항상 undefined 값을 가지게 된다.

 

map 메소드는 콜백함수 내부에서 반복 중인 배열을 편집할 수 있다.

// push 메소드로 반복 중인 배열에 추가하기
const members = ['휘철', '은주', '꿈', '달'];

members.forEach(function (member) {
  console.log(`${member}`);
  members.push('밤');
});

console.log(members);
// 배열을 편집해도 members의 length대로 4번만 반복하고 밤이 4번 추가된 것을 확인할 수 있다.


// 동작 순서
// 1. 초기 배열 상태:
// members2 = ['휘철', '은주', '꿈', '달']

// 2. 첫 번째 루프 (휘철):
// console.log('휘철'); 출력
// 배열에 '밤'을 추가 → members = ['휘철', '은주', '꿈', '달', '밤']

// 3. 두 번째 루프 (은주):
// console.log('은주'); 출력
// 배열에 '밤'을 추가 → members = ['휘철', '은주', '꿈', '달', '밤', '밤']

// 4. 세 번째 루프 (꿈):
// console.log('꿈'); 출력
// 배열에 '밤'을 추가 → members = ['휘철', '은주', '꿈', '달', '밤', '밤', '밤']

// 5. 네 번째 루프 (달):
// console.log('달'); 출력
// 배열에 '밤'을 추가 → members = ['휘철', '은주', '꿈', '달', '밤', '밤', '밤', '밤']

 

반복 중인 배열의 길이가 줄어드는 경우에는 반복 횟수도 줄어든다.

const members = ['휘철', '은주', '꿈', '달'];

members.forEach(function (member) {
  console.log(`${member}`);
  members.pop();
});

console.log(members);
// 동작 순서
// 1. 초기 배열 상태:
// members = ['휘철', '은주', '꿈', '달']

// 2. 첫 번째 루프 (휘철):
// console.log('휘철'); 출력
// members.pop()이 호출되어 배열의 마지막 요소 '달'가 제거됩니다.
// 배열은 이제 ['휘철', '은주', '꿈']이 됩니다.

// 3. 두 번째 루프 (은주):
// console.log('은주'); 출력
// 다시 members.pop()이 호출되어 배열의 마지막 요소 '꿈'이 제거됩니다.
// 배열은 이제 ['휘철', '은주']로 줄어듭니다.

// 4. 세 번째 루프 (달):
// 하지만 배열이 계속 줄어들어 forEach가 더 이상 순회하지 않습니다. 즉, 초기 배열의 길이인 4번이 아닌, 2번만 순회합니다.

// 5. 최종 배열 상태:
// 최종적으로 배열은 ['휘철', '은주']가 됩니다.

 

마지막으로 주의해야 할 점은 forEach, map 메소드의 최대 반복 횟수는 메소드를 처음 호출할 때 그 당시 요소의 갯수이다.

 

단순한 반복 작업일 경우에는 forEach 메소드, 반복 작업을 통해서 새로운 배열이 필요한 경우에는 map 메소드를 활용하면 된다.