Array.forEach 자바스크립트 루프

원본: https://www.freecodecamp.org/news/javascript-foreach-js-array-for-each-example/

배열 관련 자바스크립트 코드를 작성하다 보면 배열의 값을 조작하거나 출력하기 위해 루프를 돌아야하는 경우가 있습니다.

이 포스트에서는 자바스크립트의 forEach() 메소드를 사용하여 여러 타입의 배열에서 루프를 도는 방법과 이 방법이 for 문과 어떻게 다른지 알아보겠습니다.

자바스크립트에는 forEach() 메소드 뿐만 아니라 다양한 루프 메소드가 있으며 대부분 약간의 차이가 있다는 점 말고는 거의 동일한 기능을 수행합니다.

자바스크립트 forEach

forEach() 메소드는 배열의 모든 요소를 돌며 각 요소와 인덱스를 받는 함수를 실행하게 합니다.

forEach 루프의 문법과 매개변수

다음은 이 루프의 표준 작성 방법입니다.

array.forEach(callbackFunction);
array.forEach(callbackFunction, thisValue);

콜백 함수는 3개의 인수를 받지만 모든 인수가 반드시 받아야 하는 값은 아닙니다. 다음은 일반 함수와 ES6 메소드를 사용하여 콜백 함수를 선언하는 예제입니다:

// 현재 요소만 사용
array.forEach((currentElement) => { /* ... */ })
array.forEach(function(currentElement) { /* ... */ })

// 현재 요소와 인덱스 사용
array.forEach((currentElement, index) => { /* ... */ })
array.forEach(function(currentElement, index) { /* ... */ })

// 현재 요소와 인덱스, 전체 배열 사용
array.forEach((currentElement, index, array) => { /* ... */ })
array.forEach(function(currentElement, index, array){ /* ... */ })

// 모든 인수와 this 까지 사용
array.forEach((currentElement, index, array) => { /* ... */ }, thisValue)
array.forEach(function(currentElement, index, array) { /* ... */ }, thisValue)

위의 구문이 혼란스러워 보일 수도 있지만 이는 사용하려는 값에 따라 루프를 다르게 작성하는 일반적인 구문입니다.

사용된 매개변수에 대해 알아보겠습니다:

  • callbackFunction: 콜백 함수는 모든 요소에 대해 한 번씩 실행되는 함수이며 콜백 함수 내에서는 다음의 인수를 사용할 수 있습니다.
    1. currentElement: 이는 필수 값 으로 이름에서 알 수 있듯이 루프가 발생할 때 현재 처리 중인 배열의 요소를 의미합니다.
    2. index: 이는 현재 요소의 인덱스를 전달하는 옵셔널 인수입니다.
    3. array: 현재 루프를 돌고 있는 전체 배열을 전달하는 옵셔널 인수입니다.
  • thisValue: 콜백 함수에서 사용할 this 값을 지정합니다.

요약하면 콜백 함수는 배열의 모든 요소에 대해 현재 처리 중인 요소, 인덱스, 전체 배열을 인수로 받아 실행됩니다.

자바스크립트 forEach 예제

다른 실제 사용 예제를 살펴보기 전에 콜백 함수에 전달되는 인수와 그 사용 방법을 알아보겠습니다.

currentElement 인수 사용 방법

다음과 같이 이름, 나이, 월급, 통화 항목을 가지는 배열이 있다고 가정해 보겠습니다:

const staffsDetails = [
  { name: "Jam Josh", age: 44, salary: 4000, currency: "USD" },
  { name: "Justina Kap", age: 34, salary: 3000, currency: "USD" },
  { name: "Chris Colt", age: 37, salary: 3700, currency: "USD" },
  { name: "Jane Doe", age: 24, salary: 4200, currency: "USD" }
];

여기서 배열에 들어있는 모든 이름을 표시하려면 개발자 도구를 열고 다음과 같이 console.log() 메소드와 함께 자바스크립트 코드를 작성하면 됩니다:

staffsDetails.forEach((staffDetail) => {
  const sentence = `I am ${staffDetail.name}.`;
  console.log(sentence);
});

결과물:

forEach 예제

Note: 위와 같이 요소가 key/value 쌍을 가지는 객체인 경우 currentElement를 디스트럭처링(destructuring)하여 값을 가져올 수도 있습니다.

staffsDetails.forEach(({ name }, index) => {
  const sentence = `I am ${name}.`;
  console.log(sentence);
});

index 인수 사용 방법

다음의 예제와 같이 index 인수를 사용하여 각각의 배열 항목에서 인덱스를 사용할 수 있습니다.

staffsDetails.forEach((staffDetail, index) => {
  const sentence = `index ${index} : I am ${staffDetail.name}.`;
  console.log(sentence);
});

결과물:

forEach index 예제

array 인수 사용 방법

array 인수는 루프를 돌고 있는 원본 배열을 가리키는 세 번째 인수입니다. 예제로 다음과 같이 콘솔 출력을 해볼 수 있습니다.

staffsDetails.forEach((staffDetail, index, array) => {
  console.log(array);
});

위의 코드를 실행하면 현재 배열 요소가 4 개 이기 때문에 전체 배열을 4 번 출력하게됩니다. 간략한 예제를 보겠습니다:

const scores = [12, 55, 70];

scores.forEach((score, index, array) => {
  console.log(array);
});

결과물:

forEach array 예제

지금까지 콜백 함수의 모든 인수를 사용해 봤습니다. for 문과 다른 점을 확실하게 확인하기 위해 몇 가지 예제를 더 살펴보겠습니다.

forEach 메소드로 모든 수의 합 구하기

scores 라는 배열이 있다고 가정해 보겠습니다. 다음과 같이 배열에서 루프를 돌아 모든 숫자를 더할 수 있습니다:

const scores = [12, 55, 70, 47];

let total = 0;
scores.forEach((score) => {
  total += score;
});

console.log(total);

결과물:

모든 수의 합 구하기

앞선 직원 목록 예제에서 직원들의 월급 총 합을 계산하려면 다음과 같이 코드를 작성할 수 있습니다:

let totalSalary = 0;
staffsDetails.forEach(({salary}) => {
  totalSalary += salary;
});

console.log(totalSalary + " USD");

결과물:

직원들의 월급 총합 계산

forEach 콜백 함수에서 조건문 사용하기

루프를 돌 때 일반적인 for 문에서 하는 것 처럼 특정 조건을 적용하고 싶을 때가 있습니다. 이러한 조건은 배열의 모든 요소에 대해 실행되는 콜백 함수에서 작성하면 됩니다.

예를 들어 이전 직원 목록 예제에서 월급이 4000 보다 크거나 같은 사람의 이름만 표시하려면 다음과 같은 코드를 작성할 수 있습니다:

staffsDetails.forEach(({name, salary}) => {
  if(salary >= 4000){
    console.log(name);
  }
});

결과물:

forEach 루프와 조건문 예제

forEach 메소드와 for 문 비교

이 둘은 매우 유사하지만 각각의 루프에는 다음과 같은 고유한 기능이 있습니다.

루프의 break, continue

for 문에서는 루프를 돌다가 특정 조건이 충족되면 루프를 중단 하거나 코드 블록을 넘어갈 수 있습니다. 이러한 동작은 break 명령어와 continue 명령어로 구현할 수 있지만 forEach() 메소드에서는 작동하지 않습니다.

const scores = [12, 55, 70, 47];

scores.forEach((score) => {
  console.log(score);

  if (score === 70) 
    break;
});

결과물:

forEach 예외

위의 코드를 실행하면 Illegal break statement 에러가 발생합니다. continue 명령어도 마찬가로 비슷한 에러가 발생합니다.

누락된 요소가 있는 배열

또 다른 주요한 차이점으로는 다음과 같이 배열에 누락된 값이 있는 경우입니다:

const studentsScores = [70, , 12, 55, , 70, 47];

위와 같은 배열은 개발자의 오류가 있었거나 다른 원인이 있었을 수 있지만 for 문과 forEach() 메소드는 이러한 배열에 대해 다른 접근 방식을 가집니다.

for 문은 누락된 값이 있는 경우 undefined를 리턴하는 반면 forEach() 메소드는 이 항목을 건너뜁니다.

for 문

const studentsScores = [70, , 12, 55, , 70, 47];

for (i = 0; i < studentsScores.length; i++) {
  console.log(studentsScores[i]);
}
결과물:
for 문 누락 항목 처리

forEach 메소드

const studentsScores = [70, , 12, 55, , 70, 47];

studentsScores.forEach((stundentScore) => {
  console.log(stundentScore);
});
결과물:
forEach 누락 항목 처리

정리

이 포스트에서는 모든 타입의 배열에서 루프가 가능한 forEach() 메소드를 사용하는 방법을 알아봤습니다.

이를 사용하면 for 문 보다 더 깔끔하고 읽기 쉬운 코드를 작성할 수 있습니다.

또한 for 문과의 차이점을 비교하여 각 기능의 차이를 알아봤습니다.

관련 글